
=======================================================================================================================
=======================================================================================================================
================================================= MISSING TRANSLATION =================================================
=======================================================================================================================
=======================================================================================================================


=== campaign/symphony_8_io_devices/meta.txt ===

$78454657849319* IO Devices


=======================================================================================================================
=======================================================================================================================
================================================= OUTDATED TRANSLATION ================================================
=======================================================================================================================
=======================================================================================================================


=== asset/manual/Circuits/The screen/doc.txt ===

$76434165550872*
[large]显示模式[/large]
显示屏有四种模式，它们控制着如何在屏幕上显示内存中的数据：
0: ASCII 8 （单色 ASCII 字符模式）
1: ASCII 32（8 位色 ASCII 字符模式）
2: Pixel 8 （8 位色点阵图像模式）
3: Pixel 32（真彩色点阵图像模式）

此外，每种模式都有不同的设置选项。你可以在运行时通过屏幕的输入引脚在不同模式间切换，也可以调整模式内部的设置选项。

[large]ASCII 8 模式（单色 ASCII 字符模式）[/large]
每个字节被解释为一个 ASCII 字符，显示在 96×40 字符的屏幕上。

[b]命令：[/b]
0 切换模式
1 设置数据偏移量
2 设置前景色
3 设置背景色
4 设置字体

[large]ASCII 32 模式（8 位色 ASCII 字符模式）[/large]
每组相邻的 4 个字节中的前三个分别被解释为 ASCII 字符、前景色和背景色。

8 位颜色由 3 位红色、3 位绿色和 2 位蓝色组成，如下所示：
[b][color=#ff5555]RRR[/color][color=#55ff55]GGG[/color][color=#5555ff]BB[/color][/b]

[b]命令：[/b]
0 切换模式
1 设置数据偏移量

[large]Pixel 8 模式（8 位色点阵图像模式）[/large]
每个字节被解释为一个像素的颜色，由 3 位红色、3 位绿色和 2 位蓝色组成，如下所示：
[b][color=#ff5555]RRR[/color][color=#55ff55]GGG[/color][color=#5555ff]BB[/color][/b]

像素模式下，屏幕宽高比为 4:3，分辨率最低为 4×3，最高为 1024×768。
实际的分辨率由 2 号选项的数值 setting 依照下式确定：
4 × (setting + 1) : 3 × (setting + 1)

[b]命令：[/b]
0 切换模式
1 设置数据偏移量
2 选择分辨率

[large]Pixel 32 模式（真彩色点阵图像模式）[/large]
每组相邻的 4 个字节中的前三个被解释为一个像素的颜色，红色、绿色和蓝色各一个字节：
[b][color=#ff5555]RRRRRRRR[/color][color=#55ff55]GGGGGGGG[/color][color=#5555ff]BBBBBBBB[/color][/b]

像素模式下，屏幕宽高比为 4:3，分辨率最低为 4×3，最高为 1024×768。
实际的分辨率由 2 号选项的数值 setting 依照下式确定：
4 × (setting + 1) : 3 × (setting + 1)

命令：
0 切换模式
1 设置数据偏移量
2 选择分辨率

[large]ASCII 字体[/large]
屏幕组件提供四种控制台 ASCII 字体，它们分别对应不同的代码页：

[large][b]IBM 437（cp437）[/b][large]
[image="TC_cp437.png"]

[large][b]MS-DOS 文本（cp850）[/b][large]
[image="TC_cp850.png"]

[large][b]IBM APL2（cp910）[/b][large]
[image="TC_cp910.png"]

[large][b]西里尔字母（cp866）[/b][large]
[image="TC_cp866.png"]



=== campaign/symphony_5_jumps/hint_solution.txt ===

$30888506574129* 图中白色线路所示即为添加条件跳转模式所需的电路。



=== campaign/symphony_8_io_devices/meta.txt ===

$29247683714165*
在之前的关卡中，IO（外设）模式只涉及三种操作。这一关里，我们的任务是将外设操作增加到 8 种。下表列出了这 8 种操作对应的操作码（Opcode）：
[left]
   0  nop       无操作
   1  in        读取标准输入
   2  out       写入标准输出
   3  keyboard  读取键盘事件
   4  screen    改写显示屏选项
   5  time_0    读取系统时间（低 32 位）
   6  time_1    读取系统时间（高 32 位）
   7  counter   读取程序计数器
[/left]

显示屏组件能够以多种模式将内存中的数据显示出来（详见手册页面）。你可以通过显示屏的三个输入引脚向显示屏内置的寄存器中写入新的设定，从而调整显示屏的工作模式。
当你的汇编代码运行到 screen 指令处时，指令参数 A 所对应的设置项目应该被设定为指令参数 B 所对应的数值。和之前的关卡一样，这里的参数 B 既可以是一个寄存器，也可以是立即数。

实时时钟（系统时间）组件会输出自 1970 年 1 月 1 日（1970 年元旦）以来的纳秒数，即“Unix 纪元时间”或 POSIX 时间戳。输出结果位宽为 64 位。由于我们目前的计算机架构只支持 32 位数，我们需要将这个结果拆分成两个部分，分别进行读取。这里的关键在于，我们所读取的两个部分必须取自同一个时间戳，而不能分两次访问系统时钟，否则拼合后的时间可能会出错。更具体地讲，我们只有在执行“time_0”指令时才访问系统时钟。我们要将结果的高 32 位存储起来，以供后续的“time_1”指令使用。也就是说，每次运行“time_1”指令前，我们都要先用“time_0”指令刷新结果。如果此前没有遇到过“time_0”这条指令，“time_1”指令的结果应该被置为 0。

程序计数器就是控制指令偏移量的那个元件。使用读取指令访问这个元件时，返回的结果应该是当前指令所处的偏移量。

键盘组件会监听来自你的真实键盘的输入事件。它会将监听到的按键操作存入按键事件队列中，每次访问这个组件时，它都会返回队列最前端（最早发生）的按键事件。键盘组件输出的键码是 8 位数值，而你发送到电脑寄存器中的数值应该是一个 16 位的拼合值，它包含按键事件的键码和事件性质（按下/释放）：

D = 键位按下/弹起（key down）
V = 键码（key value）
[highlight]0000000D VVVVVVVV[/highlight]



=== presenter/board_ui/bottom_panel/common.nim ===

$81974422302188* 查看手册页面



=== presenter/board_ui/bottom_panel/component_description.nim ===

$39851490511821* 使用实体键位模式


=======================================================================================================================
=======================================================================================================================
================================================= FINISHED TRANSLATION ================================================
=======================================================================================================================
=======================================================================================================================


=== asset/manual/Assembly/Assembly programming/doc.txt ===

$29435797471674*
[large]概述[/large]
汇编语言的目的是为机器可以直接执行的指令提供人类可以直接阅读的别名。

汇编语言的语法通常都会遵循一些常见的约定。如果你能充分理解游戏中使用的汇编语言，你应该也能读懂大多数真实 CPU 架构所使用的汇编语言。

通常，一条指令的语法以一个描述该指令的缩写词（称为[color=#9966ff]助记符[/color]，[color=#9966ff]mnemonic[/color]）开头，后跟一组[color=#66ccff]操作数[/color]（[color=#66ccff]operand[/color]）：[box][color=#9966ff]mov[/color] [color=#66ccff]r1[/color], [color=#66ccff]4[/color][/box]

多数汇编语言都没有复杂的段落语法，它们可以逐行拆分为一系列汇编指令。

[large]操作数（operands）[/large]

多数指令都需要包含一些变量，称作[color=#66ccff]操作数[/color]。常见的操作数有以下几种：

[b]寄存器（register）[/b]
上例中，[color=#66ccff]r1[/color] 是一个寄存器类型的操作数。编译机器码时，这个操作数会被翻译为指令集中给定的二进制编号，例如 001。

[b]数值（number）[/b]
上例中，数字 [color=#66ccff]4[/color] 是一个立即数类型的操作数。编译时，它会按照 100 的位模式原样插入机器码中。

[b]标签（label）[/b]
在确定跳转指令的目标位置时，我们通常希望跳转坐标可以由编译器从代码中自动推导，而不是由我们手动硬编码。标记跳转位置的功能可以通过标签语法实现：[box][color=#9966ff]jmp[/color] [color=#66ccff]my_label[/color]
...
[color=#66ccff]my_label:[/color][/box]
标签的语法是在单独一行中键入标签名，后接一个冒号（:）。

[large]其它常用语法特性[/large]

[b]注释[/b]
按汇编语言的标准惯例，每一行中，分号 [highlight];[/highlight] 之后的所有内容都被视为注释，汇编器会忽略它们，例如：
[box][color=#eeeeee]mov r1, 123 [/color][color=#999999]; 将 123 移入 r1[/color]
[/box]

[b]字面值[/b]
你可以像这样在汇编指令之间直接插入数据：
[highlight]U8 123[/highlight]
这里我们插入了一个整数 123。它会被汇编器原样插入到程序存储器的对应位置中，作为编译后的代码的一部分存在。[highlight]U8[/highlight] 表示“无符号 8 位整数”，你可以增加这个数字来插入位宽更大的数值，但位宽必须是 8 的倍数。
你也可以像这样插入 ASCII 字符的值，字符串需要用双引号括住：
[highlight]"Hello"[/highlight]
注意，字面值不是立即数，它更接近打孔卡片编程时设定的指令。它会被整体存入程序存储器，而立即数则是作为指令的一部分存在。

[b]常量（const）[/b]
常量可用于为你的寄存器或其他操作数取新名称。常量以关键字“const”定义，例如：
[highlight]const ROTATION = r0[/highlight]
在这个例子中，“ROTATION”成为了 r0 的别名。为寄存器创建别名可以提高你的代码可读性。

[b]保留区段（sections）[/b]
在地址（偏移量）之前插入 [highlight]@[/highlight] 记号，可使汇编器从该行指令开始，在编译后的机器码中持续写入 0，直至到达该地址为止。例如：
[highlight]@0x800[/highlight]

[b]包含文件（include）[/b]
你可以在代码中包含其他汇编文件，例如，要包含父文件夹中的文件“std_lib.asm”，你只需要添加下面的代码：
[highlight]include ../std_lib[/highlight]

包含另一个汇编文件后，汇编器会将它的汇编结果插入到 `include` 语句所在的位置。你可以直接使用被包含文件中定义的标签和 'set' 名称，前提是这些名称在被包含的文件中已通过 `pub` 关键字前缀暴露出来，例如：
[highlight]pub print:[/highlight]

要访问被包含的文件中的名称或标签，需要在名称前加上文件名和一个点，例如：
[highlight]jmp std_lib.print[/highlight]
利用这个功能，你可以创建一个标准函数库，然后在其它关卡中调用这些函数。你只需将库文件放在关卡文件夹的上级文件夹中，并将函数入口处的标签暴露出来即可。



=== asset/manual/Assembly/Assembly programming/title.txt ===

$81923869207578*
汇编代码



=== asset/manual/Assembly/Language creation/Fields/doc.txt ===

$57024194971618*
[highlight][fields][/highlight] 区段定义了可以在指令中使用的枚举域，以及许可的枚举值。例如：

[box][fields]
register
r0 000
r1 001
r2 010
r3 011

condition
eq 00
ne 01
cs 10
hs 10
[/box]

枚举域之间以空行分隔，每个枚举域以第一行的枚举域名称开头（例如 [highlight]register[/highlight]），后跟一个或多个由“枚举名+枚举值”构成的键对（每行一对，例如 [highlight]r0 000[/highlight]）。枚举值是由 0 和 1 构成的位模式，同一枚举域中的所有值必须具有相同的位宽度。

枚举域可以作为操作数，参与构成指令：
[box]mov r1, r3[/box]

[b]缺省枚举值[/b]
某些现实中的指令集架构（如 aarch64）允许在立即数前添加可选的“#”。在本游戏中，你可以利用枚举域来模拟这个行为。你可以定义一个枚举域，其中一个枚举键名为“#”，另一个则为空（缺省名称）。出于这个目的，我们允许使用双引号括住枚举名：

[box]pound
"#" 0
"" 0[/box]

[b]内置枚举域[/b]
游戏中有两个内置（保留）的枚举域：
* [highlight]label[/highlight] 指代汇编代码中的标签（例如：[highlight]mylabel:[/highlight]）。
* [highlight]immediate[/highlight] 指代立即数。



=== asset/manual/Assembly/Language creation/Fields/title.txt ===

$32103815380062*
枚举域（fields）



=== asset/manual/Assembly/Language creation/Instructions/Operators/doc.txt ===

$20029422748716*
[b]表达式运算符[/b]
游戏为计算虚拟操作数提供了一组有限的运算符：
[box]运算符       描述                  示例           %a = -30000 时的结果
!          逻辑非                 !%a           0
&&         逻辑与                 %a && 7       1
||         逻辑或                 %a || 7       1
\==         等于                   %a == 7       0
!=         不等于                 %a != 7       1
<u         无符号小于              %a <u 7       0
<          带符号小于              %a < 7        1
>=u        无符号大于等于           %a >=u 7      1
>=         带符号大于等于           %a >= 7       0
<=u        无符号小于等于           %a <=u 7      0
<=         带符号小于等于           %a <= 7       1
>u         无符号大于              %a >u 7       1
>          带符号大于              %a > 7        0
~          按位非                 ~%a           29999
&          按位与                 %a & 7        0
|          按位或                 %a | 7        -29993
^          按位异或                %a ^ 7        -29993
+          加法                   %a + 7        -29993
-          减法                   %a - 7        -30007
*          乘法                   %a * 7        -210000
/u         无符号除法              %a /u 7       2635249153387074516
/          带符号除法              %a / 7        -4285
%          取模（余数）             %a % 7        -5
<<         逻辑左移 (LSL)          %a << 7       -3840000
>>         逻辑右移 (LSR)          %a >> 7       144115188075855637
[/box]
注意上表中没有取负运算符。不过，如果 `+` 或 `-` 运算符缺少第一个操作数，默认会用 0 代替，因此取负可以通过现有的减法运算符实现。



=== asset/manual/Assembly/Language creation/Instructions/Operators/title.txt ===

$21043147057012* 表达式运算符



=== asset/manual/Assembly/Language creation/Instructions/doc.txt ===

$64897298154598*
[large]概述[/large]
手册页面“[link="Assembly/Language creation"]自定义汇编指令集[/link]”只介绍了指令定义的基础要素。本页面旨在详细介绍其余更复杂的高级特性。

每条指令由以下几行组成：

[color=#66ff99]汇编语法[/color]
[color=#ffe666]虚拟操作数[/color]（可选）
[color=#ff6680]断言[/color]（可选）
[color=#66ccff]输出位模式/机器码[/color]
[color=#9966ff]指令描述[/color]

举例如下：
[box][color=#66ff99]jmp %offset(label)[/color]
[color=#ffe666]%high_bits = %offset / 4[/color]
[color=#ff6680]assert(%offset % 4 == 0, "Can only jump to 4 byte aligned addresses")[/color]
[color=#66ccff]01 hhhhhh[/color]
[color=#9966ff]# Jump to %offset[/color][/box]

[large][color=#66ff99]汇编语法（syntax）[/color][/large]
每条汇编语句的语法定义是一个由空白字符分隔的词元字符串，词元分为两种：[b]字面值[/b]和[b]操作数[/b]。

[b]字面值（literal）[/b]
示例中的指令助记符 [highlight]jmp[/highlight] 就是一个字面值。用户必须完全按照这个写法输入，指令才能匹配。需要注意的是，用于分隔操作数的逗号（[highlight],[/highlight]）也是一种字面值。
如果你想在汇编语法中使用百分号（[highlight]%[/highlight]）作为字面值，那你必须使用双百分号（[highlight]%%[/highlight]）进行转义，因为 [highlight]%[/highlight] 在指令集定义中是一个特殊字符。

[b]操作数（operand）[/b]
指令操作数以 [highlight]%[/highlight] 为前缀，格式为 [highlight]%name(fields)[/highlight]。
* [highlight]name[/highlight] 是一个自定义标识符（变量名）。
* [highlight]fields[/highlight] 是一个或多个先前在“枚举域”区段中定义的枚举域的名称（或内置枚举域的名称）。如果有多个枚举域，那它们彼此之间要用竖线（[highlight]|[/highlight]）分隔。

[b]空白字符（whitespace）[/b]
空白字符可以是制表符或空格。如果使用单个空白字符，那么在最终的汇编语言中，该空格是可选的。如果该空白字符后面紧跟另一个空格，那么汇编器将要求两侧的词元之间必须有空白字符。例如，一条指令的语法定义如果是 [highlight]function ()[/highlight]，那么它可以可以匹配 [highlight]function()[/highlight] 或 [highlight]function ()[/highlight]；而写成 [highlight]function  ()[/highlight]（两个空格）的话，则只匹配后者，即强制要求单词“function”和后面的括号之间有一个空格。


[large][color=#ffe666]虚拟操作数（virtual operand）[/color][/large]
上方的作为案例的跳转指令所属的指令集中，指令字长均为 4 字节，因此正确的跳转地址最低两位必然为 0。我们可以创建一个虚拟操作数，来移除这赘余的两个数位：
[box]%high_bits = %offset / 4[/box]
在随后的指令定义中，我们将使用 [highlight]%high_bits[/highlight] 作为操作数，来替换 [highlight]%offset[/highlight]。
定义虚拟操作数时允许使用的运算符列表[link="Assembly/Language creation/Instructions/Operators"]详见此处[/link]。

定义虚拟操作数时，表达式里面可以包含两个特殊的变量，[highlight]$start[/highlight] 和 [highlight]$end[/highlight]。$start 是编译之后指令起始处的地址偏移量，而 $end 是结束处的地址偏移量。这两个变量可以用于计算某个地址对当前指令的相对偏移量：
[box]%rel_offset = %offset - $end[/box]


[large][color=#ff6680]断言（assertion）[/color][/large]
断言允许你检验用户输入的指令中是否存在特定的错误。在上例中，设置断言的目的是确保用户输入的跳转地址必须为 4 的整数倍。


[large][color=#66ccff]输出位模式/机器码（machine code）[/color][/large]
上例中，指令编译后得到的机器码具有如下格式：
[box]01 hhhhhh[/box]
这里 [highlight]h[/highlight] 指代虚拟操作数 [highlight]%high_bits[/highlight]。在输出位模式中，操作数中的二进制位由操作数的首字母代表。

上面的语法也可以利用[b]位模式切片[/b]（bit slicing），等价地通过下面的语句实现：
[box]01 %offset\[8:2][/box]
位切片使用选择二进制位的标准硬件语法，其格式为[highlight]\[last:first][/highlight]，其中最高位（last）和最低位（first）都被包含在生成的切片中。

位切片可以用在任意数量的操作数上，并且可以和按操作数名称引用的方式混排。


[large][color=#9966ff]指令描述（description）[/color][/large]
指令描述是一行注释性的文本，其中可以包含任何内容。指令描述本身没有任何语法功能，它纯粹是为了向用户解释指令用途而服务的。



=== asset/manual/Assembly/Language creation/Instructions/title.txt ===

$27583144414493*
指令（instructions）



=== asset/manual/Assembly/Language creation/Patterns/doc.txt ===

$29662258275697*
[highlight][patterns][/highlight] 区段用于为指令集定义特殊的文本替换模式（宏模式），以减少重复的指令定义。宏模式定义与指令定义类似，其具体结构如下：

[color=#66ff99]宏模式签名[/color]
[color=#66ccff]汇编语法格式[/color]
[color=#9966ff]输出位模式[/color]

下面是一个使用宏模式简化指令定义的例子：
[box][patterns]

[color=#66ff99]pattern size(width, machine_code)[/color]
[color=#66ccff]U{width}[/color]
[color=#9966ff]00{machine_code}[/color]

[instructions]

mov_%s\[[color=#66ff99]size([/color][color=#66ccff]"8"[/color], [color=#9966ff]"00"[/color][color=#66ff99])[/color] | [color=#66ff99]size([/color][color=#66ccff]"16"[/color], [color=#9966ff]"01"[/color][color=#66ff99])[/color]] %a(reg) %b(reg)
0000 [color=#9966ff]%s[/color] %a %b
\# Move to %a from %b

[/box]
进行宏展开后，先前的指令定义会被替换为如下内容：
[box][instructions]

mov_[color=#66ccff]U8[/color] %a(reg) %b(reg)
0000 [color=#9966ff]0000[/color] %a %b
\# Move to %a from %b

mov_[color=#66ccff]U16[/color] %a(reg) %b(reg)
0000 [color=#9966ff]0001[/color] %a %b
\# Move to %a from %b

[/box]
这个例子中，我们首先定义了一个宏模式 size(size, machine_code)，随后在指令中调用了它。宏模式的定义以 pattern 关键字开头，后接宏模式的名称和参数列表，它们共同构成宏模式的签名（signature）。接下来的两行是两组代码片段。在生成指令集时，对应的宏签名会被这些片段替换，分别插入指令语法和编译输出的指令位模式中。

本例中，我们在指令中使用 [highlight]%s[/highlight] 作为操作数的名称。解释器会尝试逐条枚举 [highlight]%s[/highlight] 中包含的所有宏模式，并将每一种对应的模式展开到一条单独的指令定义中。每一条以此方法生成的指令定义都将继承指令原型中共有的静态字符串，而其中的宏模式会被替换为不同的版本。



=== asset/manual/Assembly/Language creation/Patterns/title.txt ===

$50803475056346*
宏模式（patterns）



=== asset/manual/Assembly/Language creation/Settings/doc.txt ===

$13660841232898*
[highlight][settings][/highlight] 区段定义了指令集的几个可配置属性：

[b]名称（name）[/b]
[box]name = "Architecture name"
[/box]指令集的名称。

[b]变体（variant）[/b]
[box]variant = "Architecture variant"
[/box]用于描述该指令集的额外标签。

[b]端序（endianness）[/b]
定义指令的字节序。
[box]endianness = big
endianness = little[/box]
默认为大端序（big endian）。

你可以[link="Computer concepts/Endianness"]在此[/link]阅读更多关于字节序的内容。

[box=info]大容量存储元件（RAM、SSD 等）有自己的端序设置，你可以用这些设置再次反转程序存储时的字节序。如果你的指令宽度恰好与内存元件的位宽匹配，编译结果会非常直观；但如果两种位宽不同，编译结果可能会很难理解。[/box]

[b]行注释（line_comments）[/b]
指定用于标记单行注释起始点的字符串。单行注释从给定的字符串模式开始，直到行尾结束。
[box]line_comments = "#"
line_comments = \[";", "//"][/box]
默认的行注释标记为 [highlight]\[";", "//"][/highlight]，即分号和双斜杠两种。

[b]块注释（block_comments）[/b]
指定用于标记块注释起始位置和结束位置的字符串。块注释从起点字符串开始，一直持续到结束字符串处，中间可以包括换行符以及额外的块注释起点字符串（但不包括结束字符串，即不允许嵌套块注释）。
[box]block_comments = {"/*":"*/"}[/box]
默认的块注释指示符为 [highlight]{"/*":"*/"}[/highlight]，与 C 语言的风格相同。



=== asset/manual/Assembly/Language creation/Settings/title.txt ===

$78090021698706*
设置（settings）



=== asset/manual/Assembly/Language creation/doc.txt ===

$41184546203403*
[large]概述[/large]

下例是一个简单的自定义汇编指令集（ISA）：
[box][fields]
register
r0 000
r1 001
r2 010
r3 011

[instructions]
mov %a(register), %b(register)
00aaabbb
\# Move a value to %a from %b

mov %a(register), %b:U8(immediate)
01000aaa bbbbbbbb
\# Move a byte to %a from %b

jmp %a(label)
10000000 aaaaaaaa
\# Jump to %a[/box]

注意，汇编指令集的定义包含两个必要部分：[highlight][fields][/highlight] 和 [highlight][instructions][/highlight]。

[large]枚举域（[fields]）[/large]
枚举域（field）允许你为特定的位模式定义专门的名称。这部分内容通常用于为寄存器设定别名。详情请参见[link="Assembly/Language creation/Fields"]此处[/link]。

[large]指令集（[instructions]）[/large]
指令（instruction）定义由一行[color=#66ff99]语法[/color]、一行[color=#66ccff]机器码[/color]和一行[color=#9966ff]描述[/color]组成：

[box][color=#66ff99]mov %a(register), %b(register)[/color]
[color=#66ccff]00aaabbb[/color]
[color=#9966ff]# Move a value from %b to %a[/color][/box]
当你在汇编语言编辑器内键入一行汇编指令时，汇编器会扫描指令定义列表，找到第一条匹配的指令[color=#66ff99]语法[/color]，然后将这条指令翻译为对应的[color=#66ccff]机器码[/color]。

[b][color=#66ff99]语法（syntax line）[/color][/b]
语法行由硬编码的字符串（不可变部分）和操作数（可变部分）组成。操作数始终以 [highlight]%[/highlight] 开头，后跟一个（在机器码中起标识作用的）名称。操作数名称后紧跟一个用括号括住的枚举域名称，它用于指示这个操作数的具体类型。枚举域的名字可以是标签（label）、立即数（immediate）或你在 [b][fields][/b] 部分中自行定义的枚举域，比如 [highlight]register[/highlight]。

[b][color=#66ccff]机器码（machine code line）[/color][/b]
指令对应的机器码由 0 和 1 以及语法行中定义的任何操作数名称的首字母组成。0 和 1 会按字面值被汇编器直译，而操作数字母则会在编译时被替换为对应的二进制值。比如上例中的 [highlight]aaa[/highlight] 在编译时会被替换为 r0 至 r3 中的一个寄存器对应的地址值，即 000 ~ 011。

[b][color=#9966ff]描述（description line）[/color][/b]
指令描述没有任何语法功能，它只为用户提供关于指令功能的说明。

除此之外，本游戏所用的汇编器还支持许多更高级的指令特性，详情请参见[link="Assembly/Language creation/Instructions"]此处[/link]。

[large]其他部分[/large]
除了 [b][fields][/b] 和 [b][instructions][/b] 之外，汇编指令集还有两个可选的部分：[b][link="Assembly/Language creation/Settings"][settings][/link][/b] 和 [b][link="Assembly/Language creation/patterns"][patterns][/link][/b]。单击链接可查看关于这两个部分的介绍。



=== asset/manual/Assembly/Language creation/title.txt ===

$67371980949119*
自定义汇编指令集



=== asset/manual/Assembly/title.txt ===

$85571962806085*
汇编代码编辑器



=== asset/manual/Circuits/Auto size/doc.txt ===

$65852115931553*
位宽（bit width）指一条传输数值的线路中包含的二进制位的个数。自动推导位宽是本游戏提供的一个特性，它允许用户用更灵活的手段搭建自己的自定义元件，让这些元件和内置元件一样，可以从元件表面设置位宽，或根据输入位宽自动推导自身的位宽。下图展示的例子是一个自定义计数器。它通过输入线路自动确定自身的位宽，并可以方便地配置自身的步进增量：
[image="example.png"]

注意，一些元件左上角的位宽标签的背景是深灰色，这意味着该元件的位宽是根据输入自动确定的。单击位宽数字后，你可以在弹出的对话框中点击星号（*）按钮，在自动推导和手动输入位宽两种模式间切换。
[image="setting.png"]

多数用于整数运算和操作的内置元件都有自动推导位宽的功能。该功能启用时，它们会根据相连的输入线路位宽确定自身的位宽，而怎么确定则因具体的元件而异。比如对于上图中的加法器而言，自动推导会使用两路输入操作数中位宽较大的那个作为元件位宽，过程中不会考虑输入进位的影响。

由于技术原因，游戏目前无法让常规的寄存器自动推导自身的位宽。如果你想要让寄存器自动计算位宽，你可以使用我们为你提供的可调位宽的版本。如上图所示，这个版本的寄存器带有蓝色的输入位宽指示引脚。蓝色引脚使用相连的数据线位宽作为自身的输入，而不处理其中的数值。这种引脚在特定的场景中非常实用。



=== asset/manual/Circuits/Auto size/title.txt ===

$18060272082456*
位宽自动推导



=== asset/manual/Circuits/Circular dependency/doc.txt ===

$57134685411828*
如果一个元件的输入随自身的输出而变化，那电路中就产生了循环依赖（circular dependency）。

[center][image="circular_dependency.png"][/center]

本游戏的电路仿真器不允许循环依赖的存在，一旦检测到循环依赖，仿真器就会报错。

唯一的例外是橙色引脚，它们不会影响同一时钟周期内的元件输出。因此，它们不会引发循环依赖。

[center][image="delay_line.png"][/center]



=== asset/manual/Circuits/Circular dependency/title.txt ===

$79928695804890*
循环依赖



=== asset/manual/Circuits/Delay/doc.txt ===

$25269304368822*
在真实硬件中，所有元件从接收到输入信号到产生输出的过程都有延迟。这一点很重要，因为电路中的信号延迟量决定了其能够运行的最高速度。

沿着导线从输入走到输出，并将路径上所有元件的延迟相加，就可以得到一条路径的延迟量。整个电路的延迟量由最慢的那条路径（瓶颈路径）决定。

除了输入引脚外，路径也可以从没有红色输入引脚的元件（如计数器或常量元件）开始，并在橙色引脚处结束。

此外，自定义元件在计算开销时，也是对每个引脚分别计算延迟量，而不是对整个元件按照瓶颈路径来计算一个统一的延迟量。这样做是为了避免让自定义元件中较快的引脚与较慢的引脚承担相同的延迟开销，尽量避免对使用自定义元件的用户带来不利的影响。



=== asset/manual/Circuits/Delay/title.txt ===

$82367602514282*
延迟量



=== asset/manual/Circuits/Short circuit/doc.txt ===

$20065838867866*
在数字电路中，两个元件在同一条线路上输出不同的值会导致短路。

[center][image="short_circuit.png"][/center]

但是，如果能在未激活的时候将输出引脚与输出线路断开，我们就能让多个引脚共享同一根输出线（总线，bus）。重要的是，在每个时钟周期内，最多只能有一个元件的输出引脚和输出线连通，否则会有短路的风险。（本游戏中，对于 1 位的输出总线而言，只要所有输出引脚都只在 [T]（高电平）时和总线连通，那么多个引脚也可以同时向总线上输出。——译注）

[center][image="switch.png"][/center]

在本仿真器中，可以断开的引脚显示为灰色。现实电路中，逻辑门的输出可以处于高阻态（Hi-Z），表现得好像是与后续电路断开一样。这种能输出高低电平和高阻态的逻辑门称作三态门。



=== asset/manual/Circuits/Short circuit/title.txt ===

$80662783536910*
短路



=== asset/manual/Circuits/The foundry/doc.txt ===

$43200267887776*
单击左上角工具栏的按钮  便可以打开元件工坊。

在元件工坊中，你可以自己随意设计独特的元件。你放置的电路具体的连接方式决定了自定义元件的功能，而摆放布局则决定了它的外形。

你放置的输入和输出端子元件会成为自定义元件的引脚。

放置在自定义元件中的探针会将其内部链接的数值暴露在元件的外观上。探针可以链接到你摆放的自定义元件上，从而实现多层嵌套数值的显示。（例如，你可以使用自己设计的寄存器来搭建一个程序计数器。游戏允许你将探针链接到这个自定义寄存器上，从而将其中保存的值显示在计数器的表面。）和游戏内置的寄存器类似，探针监测到的数值也可以绑定到汇编代码编辑器的监视槽位上。

对于元件工坊而言，电路图管理器本身也是自定义元件存储层级的管理器。电路图名称决定了元件的名称，文件夹结构则决定了自定义元件在菜单中的层级位置。



=== asset/manual/Circuits/The foundry/title.txt ===

$83185064398279*
元件工坊



=== asset/manual/Circuits/The keyboard/doc.txt ===

$18477347795935*
游戏中的键盘组件用于读取来自你的真实键盘的按键事件。

当你开始运行电路仿真，并且启用键盘侦听功能后，你的每次按键操作都会产生“按下”（key down）和“弹起”（key up）两种事件。每个时钟刻里，你都可以从键盘组件读取一个事件。已经触发但尚未读取的事件会被保存在组件内置的事件队列中，等待后续的读取操作。

[large]键盘模式[/large]
不同国家使用的键盘布局可能会有区别。比如美式布局键盘的字母区以 QWERTY 开头，而法式布局则以 AZERTY 开头。

如果你想要编写一个能读取用户输入字母的程序（比如文本编辑器），那么你大概不想和这些纷繁复杂的键位布局打交道。对你来说重要的只有每次按键发送的字符是什么。这种情况下，你应该使用键盘组件的[b]字符模式[/b]。

但如果你关心的是键位而非字符，比如说你需要编写一款用左手区域的按键进行方向控制的小游戏，那么你肯定也不想花时间思考用户到底是要用 WASD（美式布局）还是 ZQSD（法式布局）作为方向键。在这种场合，你关心的是这些按键在现实世界中所在的位置，而不是键帽上印刷的字符。这种情况下，你应该使用键盘组件的[b]实体键位模式[/b].

[large]字符模式[/large]
在字符模式下，每个键位将被映射到对应的 ASCII 值上（如果有）。例如，不管是哪种键盘布局，按键 [highlight]w[/highlight] 发送的键码都会被映射为 [highlight]0x77[/highlight]。

[large]实体键位模式[/large]
在实体键位模式下，键盘上每个键位都会被映射到唯一的坐标上。坐标由行号 X 和列号 Y 构成。X 和 Y 要被拼合在一个字节里，它们都只能被分配到 4 个二进制位，恰好对应十六进制中的 1 位数字。因此按键坐标可以用十六进制 0xXY 的形式简洁地表达。例如，空格键（X = 5, Y = 3）可以表示为 0x53。

[image="coordinate_mode.png"]

注意，主键盘区之外（黑线右侧）的按键对应的 X 值（行号）非常大。这样一来它们也能用这套坐标系统进行描述。

如果你的键盘布局和上面的图示有差别（例如笔记本电脑上的紧凑型键盘布局），那么你可以通过自行测试来确定自己的键位坐标到底是怎样映射的。



=== asset/manual/Circuits/The keyboard/title.txt ===

$11486015900582*
键盘组件



=== asset/manual/Circuits/The screen/title.txt ===

$53269020658041*
显示屏组件



=== asset/manual/Circuits/title.txt ===

$42610024611500*
电路仿真器



=== asset/manual/Computer concepts/ASCII encoding/doc.txt ===

$69772243733094*
ASCII 码是一套在 7 位整数和常用字符（主要是英文字符）之间映射转换的编码表。（屏幕组件的字符模式使用扩展 ASCII 编码显示文字，这种编码比标准的 ASCII 码多出一位，使用一个完整字节编码文字。）

ASCII 码表如下所示：
[b]码位   代码    描述[/b]
  0    NUL    
  1    SOH    标题开始
  2    STX    正文开始
  3    ETX    正文结束
  4    EOT    传输结束
  5    ENQ    查询
  6    ACK    肯定应答
  7    BEL    响铃
  8    BS     退格
  9    HT     水平制表位
 10    LF     换行
 11    VT     竖直制表位
 12    FF     换页
 13    CR     回车
 14    SO     取消变换（Shift out）
 15    SI     启用变换（Shift in）
 16    DLE    跳出数据通讯
 17    DC1    设备控制 1（XON）
 18    DC2    设备控制 2
 19    DC3    设备控制 3（XOFF）
 20    DC4    设备控制 4
 21    NAK    否定应答
 22    SYN    同步空闲
 23    ETB    区块结束
 24    CAN    取消
 25    EM     介质结束
 26    SUB    替换
 27    ESC    退出键
 28    FS     文件分隔符
 29    GS     组分隔符
 30    RS     记录分隔符
 31    US     单元分隔符
 32    SP     空格
 33    !      感叹号
 34    "      双引号
 35    #      井号
 36    $      美元符号
 37    %      百分号
 38    &      与号
 39    '      单引号
 40    (      左圆括号
 41    )      右圆括号
 42    *      星号
 43    +      加号
 44    ,      逗号
 45    -      减号
 46    .      句点
 47    /      正斜杠
 48    0       
 49    1       
 50    2       
 51    3       
 52    4       
 53    5       
 54    6       
 55    7       
 56    8       
 57    9       
 58    :      冒号
 59    ;      分号
 60    <      小于号
 61    =      等于号
 62    >      大于号
 63    ?      问号
 64    @      
 65    A       
 66    B       
 67    C       
 68    D       
 69    E       
 70    F       
 71    G       
 72    H       
 73    I       
 74    J       
 75    K       
 76    L       
 77    M       
 78    N       
 79    O       
 80    P       
 81    Q       
 82    R       
 83    S       
 84    T       
 85    U       
 86    V       
 87    W       
 88    X       
 89    Y       
 90    Z       
 91    \[      左方括号
 92    \\      反斜杠
 93    ]      右方括号
 94    ^      脱字符/扬抑符
 95    _      下划线
 96    `       
 97    a       
 98    b       
 99    c       
100    d       
101    e       
102    f       
103    g       
104    h       
105    i       
106    j       
107    k       
108    l       
109    m       
110    n       
111    o       
112    p       
113    q       
114    r       
115    s       
116    t       
117    u       
118    v       
119    w       
120    x       
121    y       
122    z       
123    {      左花括号
124    |      竖线
125    }      右花括号
126    ~      波浪号
127    DEL    删除键



=== asset/manual/Computer concepts/ASCII encoding/title.txt ===

$75719044675256*
ASCII 编码



=== asset/manual/Computer concepts/Binary/doc.txt ===

$39479426746559*
我们在日常生活中使用的数字通常是十进制数。在一个十进制数的末尾添加一个 0，这个数字就会变为原先的 10 倍。

二进制的基数为 2，因此在一个二进制数的末尾添加一个 0，只会使其变为原来的 2 倍。换句话说，每一位数字都代表 2 的幂。例如，用颜色区分[color=#c54d5e]二进制[/color]和[color=#e49f44]十进制[/color]：

[color=#c54d5e]  1[/color] = [color=#e49f44]1[/color]
[color=#c54d5e] 10[/color] = [color=#e49f44]2[/color]
[color=#c54d5e]100[/color] = [color=#e49f44]4[/color]

要在二进制中表示 6，我们可以简单地把 4（100）和 2（10）相加：

[color=#c54d5e]110[/color] = [color=#e49f44]6[/color]

在二进制下，加法、乘法等运算与十进制下的规则相同，唯一的区别是进位的规则从“满十进一”变成了“满二进一”。



=== asset/manual/Computer concepts/Binary/title.txt ===

$73447955210779*
二进制



=== asset/manual/Computer concepts/Bytes/doc.txt ===

$64065714320299*
本游戏中，你需要搭建一台 8 位计算机。在现实操作中，这通常意味着玩家需要在许多地方铺设 8 条并行的导线。
为了减轻这种枯燥的重复工作，我们引入了“字节”的概念。一根单字节的线路其实就是一束虚拟的 8 根导线。

在模拟器运行时，无论是整型输入/输出引脚，还是整型数值的线路，其状态都由一个整数来表示，而不再使用颜色（[T] 或 [F]）来区分。



=== asset/manual/Computer concepts/Bytes/title.txt ===

$68430971305988*
字节



=== asset/manual/Computer concepts/De Morgan's laws/doc.txt ===

$13079267765950*
四个基本逻辑门的真值表是对称的。你可以通过[color=#6e9759][b]对输入取反[/b][/color]（垂直箭头）或[color=#595f99][b]对输出取反[/b][/color]（水平箭头）来对这几种逻辑门进行变换，如下图所示。

[center][image="de morgan.png"][/center]

注意：

1. 你可以从任意基本逻辑门转换到另一种，最多只需要对输入和输出同时取反。
2. 通过对输出取反，可以在或门与或非门之间互相转换，同样的操作也适用于与门和与非门。事实上，NOR 的意思就是“非或”（NOT OR），而 NAND 的意思是“非与”（NOT AND）。注意，或门与或非门（OR/NOR）的元件形状除了尖端代表取反的小圆点外，是完全相同的。与门和与非门（AND/NAND）也是如此。
3. 对输出取反，会使真值表最后一行全部反转。对输入取反，则会使真值表的最后一行以中心为轴左右镜像。



=== asset/manual/Computer concepts/De Morgan's laws/title.txt ===

$66359790889628*
德摩根定律



=== asset/manual/Computer concepts/Endianness/doc.txt ===

$78199387512682*
通常，我们会按内存地址递增的顺序从左到右显示数据。这样，当字符按地址递增顺序存储时，ASCII 文本自然也会从左到右显示。

[box]      内存（十六进制）  | ASCII
地址:  0  1  2  3  4 | 0 1 2 3 4
数据: [color=#ff6680]48[/color] [color=#ffe666]65[/color] [color=#66ff99]6C[/color] [color=#66ccff]6C[/color] [color=#9966ff]6F[/color] | [color=#ff6680]H[/color] [color=#ffe666]e[/color] [color=#66ff99]l[/color] [color=#66ccff]l[/color] [color=#9966ff]o[/color]
[/box]

此外，书写数字的惯例是最高有效位在左边，例如十三写作 [color=#ff6680]13[/color] 而不是 [color=#ff6680]31[/color]。

基于这个惯例，像 0x[color=#66ccff]12[/color][color=#66ff99]34[/color][color=#ffe666]56[/color][color=#ff6680]78[/color] 这样的多字节数字在内存中的直观表示方式是：

[box]      内存（十六进制）
地址:  0  1  2  3
数据: [color=#66ccff]12[/color] [color=#66ff99]34[/color] [color=#ffe666]56[/color] [color=#ff6680]78[/color][/box]

这种表示方式称为[b]大端序[/b]（big endian），因为较高位（更重要）的字节存储在较低的内存地址中。

然而，从算法角度讲，数位的增长方向与文本的书写方向相反会带来一些不便。某些应用（如密码学）需要处理任意位数的数字（高精度整数），这就要求我们能够任意扩展数字的位数或移除前导零。在大端序下，这些操作往往涉及到改写数组的头指针，或将整个数组中的所有元素进行移动，这会降低算法的效率或安全性。要解决这些问题，一种自然的思路是，我们可以将数字按数位由低到高的顺序进行存储（例如将十三写作 31，先个位再十位），这样我们就可以在不更新指向该数字的头指针的情况下对它的位数进行任意扩展。但这样一来，我们把这个数字嵌入字符串时就要处理文本和数字顺序相反的问题（或者我们也可以实现两种方向的动态数组）。

优先存储数字的最低有效位还有一些别的好处。例如，我们经常需要截取出一个数字的低位，而较少遇到只需要高位的情况。将最低有效位优先存储，同样意味着可以在不改变头指针的情况下截取低位数字。

这种在计算上更自然的、将最低有效位优先存储的约定，被称为[b]小端序[/b]（little endian）。不过，由于数值是按字节分组的，而每个字节内部，数字仍然按传统方向（大端序）显示，这常常让小端序的显示变得更加混乱。例如，0x[color=#66ccff]12[/color][color=#66ff99]34[/color][color=#ffe666]56[/color][color=#ff6680]78[/color] 在内存中实际表示为：

[box]      内存（十六进制）
地址:  0  1  2  3
数据: [color=#ff6680]78[/color] [color=#ffe666]56[/color] [color=#66ff99]34[/color] [color=#66ccff]12[/color][/box]

假如人们当初约定数位增长和文本书写的方向一致，或许我们就不需要这一页手册了。（当代阿拉伯文的书写顺序和数位增长的方向是一致的，都是自右向左。不过由于书写数字时是先写高位，所以数字和文字的书写顺序又相反了。——译注）

如今，现代 CPU 都采用小端序，并且它已逐渐成为计算机领域里事实上的标准，不过一个常见的例外是 TCP/IP 协议，它使用大端序来存储数字。



=== asset/manual/Computer concepts/Endianness/title.txt ===

$25715726162519*
字节序



=== asset/manual/Computer concepts/Negative numbers/doc.txt ===

$22037524510182*

本游戏里，表示负数的方法叫做“补码”（two's complement）。它是现代计算机中表示负整数的标准方法。补码表示法的几个重要特点如下：

1. 要在正数和负数之间切换，你只需将所有数位反转，然后将结果加 1。
2. 如果最高位是 [T]，那么这个数一定是负数。
3. 整数加法器在有符号和无符号模式下都能正常工作。
4. 每个整数的表示方式是唯一的。

在计算机发展早期，补码的主要竞争对手是“反码”（one's complement）。反码的主要优点是改变数字的符号很简单，只需将每一位取反即可。然而，反码中 0 有两种表示方式（正零和负零），这让比较操作变得更麻烦了。（除此之外，还有“原码”（sign-magnitude）表示法：最高位为符号位，后续数位为数值位。和反码类似，原码也有正零和负零的问题。——译注）

另一种有趣的表示法是“负二进制”（基数为-2），其中每一位的数值符号在正负之间交替。如果你对此兴趣，可以自行查阅更多资料。



=== asset/manual/Computer concepts/Negative numbers/title.txt ===

$64907157003500*
负数表示法



=== asset/manual/Computer concepts/Truth tables/doc.txt ===

$16579770195459*
游戏中经常出现输入-输出对应关系表。这种表格通常被称为[b]真值表[/b]。

[center]
输入 0 [F][T][F][T]
输入 1 [F][F][T][T]
输出   [T][T][T][F]
[/center]

和代数方程类似，在实际的真值表中，“输入”和“输出”往往用变量名来表示。此外，多数文献资料会用 0/1 或假/真来表示电路的通断状态，游戏中则主要使用色块 [F]/[T]。



=== asset/manual/Computer concepts/Truth tables/title.txt ===

$39788153942181*
真值表



=== asset/manual/Computer concepts/Turing complete/doc.txt ===

$38118080841071*
某些计算设备，例如简单的计算器，能执行的算法是有限的。

它们无法执行需要任意次循环或递归的计算。从技术上讲，没有循环或递归能力的机器只能处理组合逻辑。

而图灵完备的计算机则非常强大，这种强大不等于“快速”。一台图灵完备的机器可能只有一个主频很低的 CPU，它的强大之处在于它能执行一切理论上可行的计算。

（邱奇-图灵猜想称，任何在直觉上被认为是“可计算的”问题，都能被一台图灵机计算。而所谓可计算的问题，是指对于这一问题而言存在一套给定的算法（一系列操作指令），在接收到任何合法的输入后，都能在有限步骤之内给出解。图灵机是一种强大的计算模型，但它的存储设备容量是无限的，现实世界中的计算设备则有存储能力的上限。除去这个区别，如果一台机器能够完全模拟图灵机的操作，那么这台机器就称作是图灵完备的。——译注）



=== asset/manual/Computer concepts/Turing complete/title.txt ===

$88124920557040*
图灵完备



=== asset/manual/Computer concepts/Universal gates/doc.txt ===

$11499640163947*
事实证明，仅用与非门（NAND）或仅用或非门（NOR）就能搭建出一台计算机所需的所有逻辑电路。这两种逻辑门被称作通用逻辑门（universal gates）。阿波罗计划使用的导航计算机就是完全由或非门构成的。这台诞生于六十年代的计算机只有区区 4 KB 内存和 32 KB 外存，但它依然成功地将宇航员送上了月球。（除此之外，阿波罗计划所使用的程序是用导线手动编织在磁芯存储器阵列上的，同样令人叹为观止。——译注）

现代计算机并非完全由某一种通用逻辑门构成，但人们一般会优先选用与非门，因为它延迟更低、占用面积也更小。



=== asset/manual/Computer concepts/Universal gates/title.txt ===

$24291443495513*
通用逻辑门



=== asset/manual/Computer concepts/title.txt ===

$42755701050268*
计算机术语



=== campaign/always_on/hint_0.txt ===

$62210202128540* 注意到了吗？输入值其实无关紧要。



=== campaign/always_on/hint_solution.txt ===

$33906573915218* 只需要选用一个输入端不接收任何数值时也会输出 [T] 的逻辑门即可。



=== campaign/always_on/meta.txt ===

$18258110894478* 你刚刚在这一关里解锁了第一个手册页面。这个页面非常重要，请确保你能明白其中的内容。

$61066799501731* 长明灯

$85978749941194* 请搭建一个始终输出 [T] 的电路。



=== campaign/and_gate/hint_0.txt ===

$68158507707802* 与门可以理解为“非”“非”“与”（NOT-NOT-AND）门，也就是“非”“与非”（NOT-NAND）门。



=== campaign/and_gate/meta.txt ===

$18221128000007*
这一关的任务是搭建一个与给定真值表匹配的电路。
[tip]多数关卡都自带提示（上方的灯泡按钮）。如果你卡关了，可以看看这些提示。[/tip]

$28388869498626* 眼下，在地球上所有的受试对象中，大象的表现遥遥领先。不过考虑到大脑尺寸的差异，你做得也还算不错。

$70892117360845* 与门（AND）



=== campaign/and_gate_3/hint_0.txt ===

$34539182309616* 更大的与门其实就是多个与门首尾相接。



=== campaign/and_gate_3/meta.txt ===

$28751026881977* 搭建一个有三路输入的与门（AND）。

$32912994842868* 三路与门



=== campaign/any_doubles/hint_0.txt ===

$10183449965120* 要检查是否至少有 2 路输入为 [T]，我们可以将输入拆分成对，逐对进行判断。



=== campaign/any_doubles/hint_1.txt ===

$83867604619162* 要判断一对输入是否都为 [T]，可以对它们执行与（AND）运算。



=== campaign/any_doubles/hint_solution.txt ===

$34521278233301* 请自行探索更好的解法吧！

$43216513907358* 这种解法不是最优雅或者最高效的。



=== campaign/any_doubles/meta.txt ===

$43068867747292*
本关有 4 路输入。
有 2 路或更多的输入为 [T] 时，输出 [T]。

[tip]别把这一关想得太复杂。[/tip]

$81647833476822* 成双成对



=== campaign/assembly_programming/default.isa ===

$11603603520594* 将 %b 中的数值写入 %a。



=== campaign/assembly_programming/meta.txt ===

$17226968214352* 打孔式编程太无聊了。和上一关一样，这一关里你要计算一个整数加 5 的结果。不过这一次，你需要使用汇编语言。

$72990407719621* 汇编程序

$73801373825270*
汇编语言本质上说，就是为电脑运行的指令取一组别名，把它们转化为人类能读懂的文本。

习惯上，汇编语言的指令要遵循特定的语法：每条指令都以一个单词缩写开头（称作助记符，[color=#9966ff]mnemonic[/color]），用于描述指令的功能；其后跟随一组操作数（[color=#66ccff]operand[/color]），例如：
[highlight][color=#9966ff]mov[/color] [color=#66ccff]r1[/color], [color=#66ccff]r2[/color][/highlight]

另外，习惯上，指令的作用目标总是放在操作数列表的最左侧。比如，上面这条指令的意思是将寄存器 r2 中的值复制（移动）到 r1 中。理解这条规则有助于你阅读真实的汇编代码。

单击程序存储器右上角的“编辑”按钮可以打开汇编语言编辑器，你可以在其中使用汇编语言编程。此外，你可以单击编辑器左上角的 spec.isa 标签页，将编辑器切换到指令集文件。在指令集文件里，你可以查阅 Overture 架构所支持的所有汇编指令。



=== campaign/assembly_programming/new_program.asm ===

$36228934755685* 将立即数 15 写入 reg 0

$41299869859669* 以（英文）分号开头的是注释行

$73562005049347* 将输入值写入 Reg 2

$80524429403045* 单击左上角的 spec.isa 标签页可切换至指令集模式并查看完整指令列表



=== campaign/assembly_programming/test.si ===

$38629344681843* {input_value} + 5 应该是 {expected_value}，而非 {actual_value}。

$47165251832545* {input_value} + 5 应该是 {expected_value}，而非高阻态。



=== campaign/assembly_programming/ui.txt ===

$27941792707668* 利用汇编语言编程，对输入加 5 并输出



=== campaign/binary_programming/default.isa ===

$31456617450268* 将 %b 中的数值写入 %a。



=== campaign/binary_programming/meta.txt ===

$12002017150690* 请单击程序存储器右上角的“编辑”按钮，用打孔卡片为你的电脑编写程序。这一关里，你的电脑需要读取一个输入并加 5，然后将结果发送到输出设备中（不必考虑溢出问题）。

$23659479615536* 既然你已经搭建了属于你自己的电脑，那么下一步自然就是学习如何在这台电脑上编程了。

$35877580485177*
你和另一种叫做海豚的生物各自成功造出了一台计算机。但你们二者中只有一种能够代表地球生物加入星系联邦。你们还得继续竞争，直到决出胜负为止。

下一个重要的里程碑是通过编程来解决复杂的实际问题，比如说迷宫寻路。

$47348572622406* 打孔编程



=== campaign/binary_programming/test.si ===

$61846111928326* {input_value} + 5 应该是 {expected_value}，而非 {actual_value}。

$81797824381193* {input_value} + 5 应该是 {expected_value}，而非高阻态。



=== campaign/binary_programming/ui.txt ===

$65391114076509* 利用二进制打孔编程，对输入加 5 并输出



=== campaign/binary_racer/meta.txt ===

$17561499905402* 这一关是我最喜欢的消遣小游戏。你需要在有限的时间内将十进制数手动转换为二进制。

$37988524800638* 二进制速算

$78267067157141*
点击下方面板的数位可以将其反转。你需要让高电平 [T] 数位的总和恰好等于给定的数值。

为通过本关，你至少需要连续通过 3 级。



=== campaign/binary_search/meta.txt ===

$16764912826624* 道破心机

$20948899837760*
这一关里，我会在心里想好一个密码，你需要猜出这个密码才能获胜。即使你猜错了，我也不会判你失败，所以你可以随便尝试任何你想尝试的数字。

请将你猜测的密码值发送到电脑的输出端。另外，如果你的猜测值过高，我会将计算机的输入设为 1；如果你的猜测值过低，输入则会被置为 0。以你的智力，或许可以利用这个信息来减少猜测的次数。



=== campaign/bit_adder/hint_0.txt ===

$32998192994042* 总和（SUM）的计算与“奇数计数技术”这一关的思路类似。

$90884846016283* 进位（CARRY）仅在两路输入都为 [T] 时为 [T]。



=== campaign/bit_adder/meta.txt ===

$10776402819741* 我们用数字丈量宇宙。所以你造的电脑必须学会计数。

$19285770105090*
如果输入为 [F]，将它视作 [b]0[/b]，如果输入为 [T]，将它视作 [b]1[/b]。以二进制方式将它们相加，使总和（SUM）为 [b]0[/b] 或 [b]1[/b]。

与普通加法一样，如果结果不能用一位数来表示，将进位数（CARRY）设为 [b]1[/b]。

$64470174232265* 半加器



=== campaign/bit_inverter/hint_1.txt ===

$40415302067949* 输出为 [T] 的电路。

$61125857472821* 因此我们要构造的是输入“([T] AND [F]) OR ([F] AND [T])”时，



=== campaign/bit_inverter/hint_solution.txt ===

$64992550674018* 由真值表可知，我们需要构造的恰是一个异或门



=== campaign/bit_inverter/meta.txt ===

$38198768813364* 可控反相器

$53559965601096* 请搭建一个电路，实现在特定条件下反转输入二进制位的功能。具体来讲，当“[color=#e49f44][b]反相[/b][/color]”输入端为 [T] 时，你需要将“[color=#e49f44][b]输入值[/b][/color]”反转后输出，否则请将其直接发送到输出端。

$66258723258123* 我们正在测试背景图像如何影响地球人的视觉认知功能。

$76209391067704* 你可能已经注意到了，这一关的任务其实和“异或门”关卡完全相同。不论我们用自然语言提出了怎样的需求，请记得真值表才是真相所在。



=== campaign/bit_inverter/ui.txt ===

$29875779381032* 输入值

$41975883966377* 当前输出

$42809920196772* 反相

$62797002040657* 预期输出



=== campaign/bit_switch/hint_0.txt ===

$22413958203952* 从真值表看，我们只需要实现一个异或门。

$46480779443140* 先暂且忽略可用组件的限制，



=== campaign/bit_switch/hint_1.txt ===

$45466715038362* 现在只要实现或门的功能，我们就能摆平这一任务。

$76027454955517* 开关组件的行为和与门非常相似，我们直接用它们取代与门。



=== campaign/bit_switch/hint_solution.txt ===

$16488212881433* 下方示例电路（错解）

$42664577834105* 因此，上面的解法中，下半部分的示例电路存在一个细微的错误。当两路输入都为 [T] 时，两个开关同时输出 [Z]，而非预期的 [F]。

$47029050705615* 错误输出

$52307576546100* 上方示例电路（XOR）

$62622482229413* 关键在于，当开关组件的“启用”引脚没有激活时，它不像与门那样，输出低电平 [F]，而是根本不输出任何东西。

$80836475394613* 因此，多个开关组件可以共享一条输出线，而不产生短路，前提是每个时钟周期内只有至多一个开关与输出线连通。



=== campaign/bit_switch/meta.txt ===

$12922292218235* 二进制开关

$25663924496537*

我们可以将高阻态（Z state）粗略地理解为断路。另一种理解方式则是将它视作与 [F] 和 [T] 都不同的第三种逻辑状态 [Z]。

引入这一逻辑状态后，如果我们将来自不同元件的两路输出直接并联，则合并后的输出态将会满足下列的真值表：

输出 0  [F][F][F][T][T][T][Z][Z][Z]
输出 1  [F][T][Z][T][F][Z][F][T][Z]
合并结果 [F][E][F][T][E][T][F][T][Z]

表中的 [E] 代表短路。它不能被视作第四种逻辑状态，因为产生这种输出时，电路将会出错（真实的数字电路则可能损坏）。因此，短路输出无法用于计算操作，它只作为真值表中的占位符出现。

$77268807700313* 利用 2 个非门和 2 个开关，搭建一个异或门（XOR）。

$88100823584262*
当不同的组件向同一条线路上输出不同的值时，电路就会发生短接错误。不过，有些元件有灰色的输出引脚。这种引脚只在激活时产生输出，未激活时则与输出线“断开”（处于高阻态）。 这一关引入的二进制开关就是这种组件。

[center][image="switch.png"][/center]

当下方的引脚处于 [F] 状态时，开关组件的输出端将被禁用。只要一次只启用至多一个开关，多个开关就可以共享一条输出线，而不引发短路。



=== campaign/byte_adder/hint_0.txt ===

$37690209655811* 本关的直观解法需使用 8 个全加器。



=== campaign/byte_adder/hint_1.txt ===

$49335074955899* 对单个二进制位，我们只需要使用已有的全加器即可。

$56143546486508* 和其他单字节组件相同，我们先将单字节线路拆分为单个二进制位线。



=== campaign/byte_adder/hint_2.txt ===

$57534334907443* 对剩余 7 个位也各自配置一个全加器。



=== campaign/byte_adder/hint_solution.txt ===

$36646953278480* 每一位加法输出的进位都是下一位的输入进位，

$69804974830322* 将各个输入输出进位引脚相连即可完成整个电路。



=== campaign/byte_adder/label.txt ===

$45190053242926* 输入进位

$76244671092409* 输出进位



=== campaign/byte_adder/meta.txt ===

$31490345812891* 将输入的两个字节的数据相加，并输出总和。输出中的每一位都应该是输入中与之对应的两个位及进位值之和。

$45061087867940*
如果结果超出了 8 位所能容纳的范围，则将输出进位（carry out）设为 [T]（你可以把它看作是第 9 位）。
  
除了两个数字外，还有一个 1 位的输入，用于接收来自其它地方的进位（carry in），它能帮助我们将多个加法器串联起来。如果其值为 [F]，你应将它视作 0，如果其值为 [T]，你应将它视作 1。

$53076615315445* 此外，这一关有大量的测例。右键单击“快速运行”按钮并输入更大的数值可以提高测例的运行速度。

$62793095496458* 单字节加法



=== campaign/byte_adder/ui.txt ===

$51758065631068* [color=#E49F44][left]进位        总和[/left][/color]



=== campaign/byte_asr/hint_0.txt ===

$86214455922761* 首先让我们回顾一下：固定位数的移位只需要分线器和集线器即可实现。



=== campaign/byte_asr/hint_1.txt ===

$11228896363898* 移动的位数可以进行二进制分解。比如，右移 3 位等价于右移 1 位 + 右移 2 位。

$11260842500047* 我们可以使用一种叫桶形移位器（barrel shifter）的电路来实现任意位数的移位。

$55175982917102* 要实现这种电路，我们只需要留意一下移位运算的特点。



=== campaign/byte_asr/hint_2.txt ===

$87506885530483* 所以我们可以将输入的数值分别右移 1 位、2 位、4 位，是否要采取这些位移操作取决于输入的位移量中对应的二进制位是否为 [T]。



=== campaign/byte_asr/meta.txt ===

$53539145017840* 算术右移

$79125097012724*
你上一关中搭建的电路是[b]逻辑[/b]右移器。将一个无符号整数逻辑右移 1 位等价于将其除以 2（向下取整）。对有符号整数，如果最高位是 [T]，我们有时不希望其符号在右移后改变。因此，如果最高位是 [T]，那么我们需要在左侧（最高位）补 1（[T]）而非补 0（[F]）。这种操作称作[b]算术右移[/b]（arithmetic shift right），在汇编语言中通常用 [b]asr[/b] 表示。

例如：[color=#e49f44]-106 asr 3[/color]
  [T] [F] [F] [T] [F] [T] [T] [F]
结果为：
 |[T] [T] [T]|[T] [F] [F] [T] [F]
       ^                     
我们在这几位插入 [T]，而非 [F]



=== campaign/byte_constant/hint_solution.txt ===

$67841603404086* 164 在二进制下的表示是 [T][F][T][F] [F][T][F][F]。



=== campaign/byte_constant/meta.txt ===

$55176290924321* 搭建一个电路，让它始终输出 164。

$55259569122850* 整型常量



=== campaign/byte_constant/ui.txt ===

$90758832592628* 搭建一个电路，让它始终输出 164。



=== campaign/byte_divide/meta.txt ===

$15513439442399* 搭建一个电路，让它能将两路整数输入相除，并输出商。如果除数为零，我们规定商也为零。注意，这一关是可选关卡，因为它的难度较高。

$55155519654685* 除法器



=== campaign/byte_divide/test.si ===

$10903561275291* {a} / {b} = {result}



=== campaign/byte_divide/ui.txt ===

$86943286745277* 将两路输入相除



=== campaign/byte_equal/hint_0.txt ===

$13186595896308* 对两个相等的数值进行按位异或，结果非常优美。



=== campaign/byte_equal/hint_solution.txt ===

$85034261531833* 两个整数按位异或，当且仅当两数字相等时，结果为 0。

$88637818475024* 要检测结果是否为 0，我们只需要检查是否每一位都是 [F]。



=== campaign/byte_equal/meta.txt ===

$16679981460998* 当两路输入相等时，输出 [T]。

$44220989927736* 整数判等



=== campaign/byte_equal/test.si ===

$18508994046371* {a} == {b} 的结果是 {value}。

$32432328437519* {a} 和 {b} 不相等

$51276780017906* {a} 和 {b} 相等



=== campaign/byte_equal/ui.txt ===

$41065065514143* 搭建一个电路，当两路输入相等时，输出 [T]。



=== campaign/byte_less_s/hint_0.txt ===

$14667194911431* 这里要注意，对于有符号补码整数，最高位需要单独考虑。这一位的效果跟无符号整数恰好相反。

$19896249626650* 如果只有一路输入的最高位是 [T] ，那么它必然较小（负数当然小于正数和 0）。

$41958293329044* 比较两个有符号整数大小的思路和比较无符号整数是类似的



=== campaign/byte_less_s/hint_1.txt ===

$82755888644217* 如果这一位不同，我们只需要比较它，就可以输出答案。



=== campaign/byte_less_s/hint_solution.txt ===

$52492743864774* 如果不然，我们只要像上一关一样，接着去比较剩下的两个 7 位无符号整数就可以了。



=== campaign/byte_less_s/meta.txt ===

$12621415211383* 搭建一个电路，当第一路输入严格小于第二路输入时，输出 [T]。注意，在本关中，输入应被视作[color=#dd6576]有符号整数[/color]。

$57911276445846* 有符号小于



=== campaign/byte_less_s/test.si ===

$18672872329218* {a} 不小于 {b}

$60636366241019* {a} 小于 {b}

$67770115019509* {a} < {b} 的结果是 {result}



=== campaign/byte_less_s/ui.txt ===

$33907970782848* 搭建一个电路，当第一路输入严格小于第二路输入时，输出 [T]。



=== campaign/byte_less_u/hint_0.txt ===

$18968293717104* 刚才提到的方法是逐位比较两个数的大小，跟我们比较十进制数的办法一样。

$45223418140453* 比如说 09 < 21，因为 0X < 2X。又比如二进制下 1100 > 1001，因为 11XX > 10XX。



=== campaign/byte_less_u/hint_1.txt ===

$23270172293605* 所以对于每一位，我们需要用一系列或门来判断更高位比较是否已经给出了答案。

$34091176621640* 这可以用异或门来实现（异或门在两路输入不同时输出 [T]）。

$38704349429368* 首先我们要确定两个数字中哪几位是不同的。

$45560562333305* 注意，我们只需要考虑存在差异的最高位，

$72421677239233* 取值不同的这些二进制位里，最高的那一位的大小决定了两个数的大小：谁是 [T]，谁更大。



=== campaign/byte_less_u/hint_2.txt ===

$37315430614523* 比如，09 < 11，等价于 09 - 11 < 0；又比如二进制下 1100 > 1001，等价于 1100 - 1001 > 0。

$73589178770254* 另一种办法是我们可以对两个数作差，然后判断结果是否小于零。



=== campaign/byte_less_u/hint_3.txt ===

$15205448412655* 更一般的表示是 Input_0 ADD (NEG Input_1)。

$19139933016995* 我们没有减法器，只能先取相反数，然后做加法。

$56709208304109* 例如，要求 1100 - 1001，我们就要计算 1100 + (-1001)。



=== campaign/byte_less_u/hint_4.txt ===

$21199347421587* 如果要表达这些数字的相反数，我们必须额外考虑第 9 位数值。

$46518640933018* 但是对于这一关而言，所有输入都是无符号数值。



=== campaign/byte_less_u/hint_5.txt ===

$11293872851403* 我们可以自定义一个 9 位的计算元件。

$17291563256662* 或者，我们也可以将负数的计算重新拆分为按位取反再加 1 这两步。



=== campaign/byte_less_u/hint_solution.txt ===

$90593296729801* 用这种方式计算相反数，我们就不必再处理那多出来的一个符号位了。



=== campaign/byte_less_u/meta.txt ===

$39605373706887* 无符号小于

$68842379350661* 搭建一个电路，当第一路输入严格小于第二路输入时，输出 [T]。注意，在本关中，输入应被视作[color=#dd6576]无符号整数[/color]。



=== campaign/byte_less_u/test.si ===

$50702714470018* {a} 不小于 {b}

$54835419299907* {a} 小于 {b}

$75551771019196* {a} < {b} 的结果是 {value}



=== campaign/byte_less_u/ui.txt ===

$88632565567686* 搭建一个电路，当第一路输入严格小于第二路输入时，输出 [T]。



=== campaign/byte_lsr/hint_0.txt ===

$75806240403820* 首先让我们回顾一下：固定位数的移位只需要分线器和集线器即可实现。



=== campaign/byte_lsr/hint_1.txt ===

$12195819154781* 移动的位数可以进行二进制分解。比如，右移 3 位等价于右移 1 位 + 右移 2 位。

$28136552692253* 我们可以使用一种叫桶形移位器（barrel shifter）的电路来实现任意位数的移位。

$88850298427736* 要实现这种电路，我们只需要留意一下移位运算的特点。



=== campaign/byte_lsr/hint_2.txt ===

$22456794338741* 所以我们可以将输入的数值分别右移 1 位、2 位、4 位，是否要采取这些位移操作取决于输入的位移量中对应的二进制位是否为 [T]。



=== campaign/byte_lsr/label.txt ===

$17566441654249* 右移量



=== campaign/byte_lsr/meta.txt ===

$26791208073532*
本关的任务是搭建一个电路，根据第二路输入的数值，将第一路输入右移对应的位数。

$36654581830314* 逻辑右移

$57629598331916*
将数字“右移”一位的意思是将每一个二进制位向右（低位方向）移动一位，并在左侧补 0。

更准确地讲，这个操作叫[b]逻辑右移[/b]（logical right shift），在汇编语言中通常用 [b]lsr[/b] 表示。

例如：[b]180 lsr 1[/b]
[left]
        [T] [F] [T] [T] [F] [T] [F] [F] 右移 1 位：
        [F] [T] [F] [T] [T] [F] [T] [F]
[/left]
又例如：[b]180 lsr 3[/b]
[left]
        [T] [F] [T] [T] [F] [T] [F] [F] 右移 3 位：
        [F] [F] [F] [T] [F] [T] [T] [F]
[/left]

$83781539475221* 你已经解锁了逻辑右移器。我们为你附送了一个逻辑左移器。



=== campaign/byte_mod/meta.txt ===

$84095392269624* 模余器

$87605997307596* 搭建一个电路，让它能将两路整数输入相除，并输出余数。如果除数为零，我们规定余数等于被除数。注意，这一关是可选关卡，因为它的难度较高。



=== campaign/byte_mod/test.si ===

$38641362389638* {a} mod {b} = {result}



=== campaign/byte_mod/ui.txt ===

$76653207214085* 对两路输入模余



=== campaign/byte_mux/hint_0.txt ===

$37740515704094* 这一关与“二进制开关”中的思路类似，

$71057700033977* 只是这里的 A 和 B 两个操作数分别对应“输入 0”和“输入 0 反相”。



=== campaign/byte_mux/label.txt ===

$63172000393911* 选通开关



=== campaign/byte_mux/meta.txt ===

$44523532982427* 当选通输入端为 [F] 时，将 A 路输入发送到输出端，否则将 B 路输入发送到输出端。

$66984132947598*
上个受试对象没能通过我们的测试，不过我们最后留下了他的狗。和地球人不一样，狗有一身丝滑的皮毛，而且还能理解简单的命令。

考虑到你们的优势正好互补，我们可能会在接下来的任务中让你们俩组队。

$75861961518456* 数据选择器



=== campaign/byte_mux/test.si ===

$15140861344476* 选通输入 {select}



=== campaign/byte_mux/ui.txt ===

$28574225028041* 选通输入 A/B



=== campaign/byte_nand/hint_0.txt ===

$88766421259023* 两个单字节数据的与非运算就是对两个操作数的每一位进行与非运算。



=== campaign/byte_nand/meta.txt ===

$11980470862173* 单字节与非

$52274910421610*
对输入的两个字节的数据进行按位与非（NAND）操作并输出结果。

例如：
输入 0 [T][T][F][F][F][T][F][F]
输入 1 [F][F][F][F][T][T][F][F]
输出   [T][T][T][T][T][F][T][T]

$66454601163361* 别担心，地球人。哪怕你最后没法通过我们的测试，我们也不会伤害你。我们可以将你放归野外，也可以给你找一个足够宽敞的动物园。



=== campaign/byte_not/hint_0.txt ===

$55051011788323* 单字节数据的非运算就是对操作数的每一位进行非运算。



=== campaign/byte_not/meta.txt ===

$54090032127372* 将输入字节中的每一位逐个取反（执行逻辑非运算）。

$60317070264440* 所以非常显然，胳膊的数量才是预测智力的主要指标。你知道吗，这颗行星上有一种海洋生物，它们的胳膊数量是你们的四倍。它们在测试中的表现比你们更好。

$65498108564418* 单字节非门

$70777086019982* 制造并使用工具的过程对动物的早期智力发育起着关键作用。

$79214241606407* 我们之前以大脑体积作为预测智力的首要指标。现在看来这个模型还是过于简化了。



=== campaign/byte_xor/hint_0.txt ===

$66692685876410* 对两个整数按位异或无非就是对每一位进行异或操作。



=== campaign/byte_xor/meta.txt ===

$41472172986798* 整型异或

$70973830134418* 搭建一个电路，对两路整数输入执行按位异或运算。



=== campaign/byte_xor/test.si ===

$54747903652562* {a} XOR {b} = {result}



=== campaign/byte_xor/ui.txt ===

$62779271315005* 搭建一个电路，对两路整数输入执行按位异或运算。



=== campaign/capitalize/meta.txt ===

$22440157378882* 首字大写

$36850349097673*
本关的输入是以 ASCII 编码形式给出的英文语句。（关于 ASCII 编码，详见[link="Computer concepts/ASCII encoding"]手册页面[/link]。）句子里的每个单词都以空格分隔，空格对应的 ASCII 值为 32。你的任务是将每个单词的首字母改写为大写形式，并将改写后的句子输出。

本关的测例输入只包含从 a 到 z 的小写字母和空格，你不需要考虑其它特殊符号。



=== campaign/capitalize/test.si ===

$37137490280093* 你还没有从字符串中读取字符“{character}”

$52976618691411* 输出应为 {char}，而非 {output}。



=== campaign/circumference/meta.txt ===

$21808795465233* 三番两次

$46884494321384*
本关里，你需要从输入端读取一个圆的半径，并计算这个圆的周长。

圆周长的计算公式为 2×π×r，

r 是输入的半径，
圆周率 π 近似取 3。

请将计算出的周长发送到输出端。



=== campaign/circumference/test.si ===

$18136442036625* 2π × {radius} 的结果是多少？



=== campaign/circumference/ui.txt ===

$24129473753872* 从输入设备读取数值

$47357954866257* * 近似取 π ≈ 3



=== campaign/conditional_jumps/meta.txt ===

$38150072401115*
要完成这一关，请你编写一段代码，反复地读取输入，直到读入的数字是 37 为止。 

然后请向输出设备发送你读取输入的总次数。

$38613585637577*
地球人，我这有一条好消息：海豚被淘汰了。

事实证明他的鳍并不适合用来敲代码。

不过我们会继续我们的测试，来看看地球人到底能做到什么地步。

$40525671378957*
这一关的目的是让你了解汇编语言中跳转指令和标签的用法。

跳转指令是专门用于覆写程序计数器的指令。

向程序计数器中写入特定的地址，意味着下一刻程序将“跳跃”到这个地址对应的代码处运行，而不是通常的步进运行。

$47703565240245* 条件跳转

$65712025748767*
你每次插入或删除一条汇编指令时，后续指令的地址都会随之发生变化。如果你只能让程序跳转到固定的地址，那你可能需要重新计算跳转地址，才能让跳转目标处的指令保持不变。

你可以使用“标签”（[color=#66ccff]label[/color]）这种语言特性来简化跳转地址的计算。标签本质上是一个常数，它的值就是自身所在的指令地址，并会随汇编代码的改变而自动更新。例如：

[box][left]
[color=#66ccff]my_label[/color]:     [color=#aaaaaa]; This is a label[/color]
[color=#9966ff]imm[/color] [color=#66ccff]my_label[/color]  [color=#aaaaaa]; Load the offset of the label[/color]
[/left][/box]
上述代码中，my_label 是第一行代码，它所在的地址为 0，因此 imm 指令会将 0 作为立即数放入寄存器中，供后续的跳转指令使用。



=== campaign/conditional_jumps/new_program.asm ===

$35642914965530* 跳转到 reg 0 中的值对应的地址（第 5 字节）

$50319416070023* 将 5 写入 reg 0

$66946505646203* 你可以像这样将标签所在的地址写入 reg 0

$67381454058237* 以冒号结尾的行是标签（label）

$78380513477546* 请翻阅指令集文件 spec.isa 以查看更多的跳转指令



=== campaign/conditional_jumps/test.si ===

$39953782121467* 最后一次读取的输入值不是 37！

$75138288162938* 你读取了 {read_count} 个输入值，但预期的读取次数为 {output}。



=== campaign/conditional_jumps/ui.txt ===

$65261628219716* 实现条件跳转功能，并调整内存元件中的汇编代码



=== campaign/count_leading_zeroes/hint_0.txt ===

$15352671410916* 这里 N 是输入的总数位，而 log2 是第一个 [T] 的位置。

$75683304945175* 除去输入为零的情况外，这个问题等价于计算 N - 1 - log2(Input)，

$83745112465243* 而计算整数以 2 为底的对数（log2）则是计算机领域里很常见的问题。



=== campaign/count_leading_zeroes/hint_1.txt ===

$40521556880682* 我们先考虑一个简化版本：

$46035077948196* 一个两位二进制数（可能是 0 ~ 3）以 2 为底的对数如何计算？



=== campaign/count_leading_zeroes/hint_2.txt ===

$32041142528569* 而 N = 2，所以前导零的个数 N - 1 - log2(Input) 分别为 1 和 0。

$88044062357651* 那么一个四位二进制数的情形又如何呢？

$88309764896321* 如果这个数小于 2，log2(Input) = 0，否则 log2(Input) = 1。



=== campaign/count_leading_zeroes/hint_3.txt ===

$24472621996685* 如果这个数字小于 4，那么这个问题就是我们刚才讨论的两位数的情形。

$42632561737634* 不管哪种情况，我们都可以将问题化简为两位数的情况。

$87709120049440* 如果这个数字大于等于 4，那么第一个非零位（[T]）一定在最高的两位里。



=== campaign/count_leading_zeroes/hint_4.txt ===

$12591714876491* 我们只需要再单独处理输入为零的情况即可。

$82513296271559* 用同样的思路，我们可以将八位数的情形化简为 4 位数。



=== campaign/count_leading_zeroes/hint_solution.txt ===

$27675083487752* 这个解法不是最优雅或最高效的。

$62535209440079* 请自行探索更好的解法吧！

$81301599100070* 最直白的处理方式是单独考虑输入为零的情况。



=== campaign/count_leading_zeroes/meta.txt ===

$18890527031365* 前导零计数

$30557055303267*
搭建一个电路，让它能从输入的最高位开始，计算有多少个连续的 [F]。

比如，对下面的输入样例而言，你的电路应该输出 3，因为前三位都是 [F]：
[F][F][F] [T][F][T][F][T]



=== campaign/count_leading_zeroes/test.si ===

$10248302990519* {input_value}（{binary_value}）应有 {count} 个前导零

$46565705342966* {input_value}（{binary_value}）应有 1 个前导零



=== campaign/count_leading_zeroes/ui.txt ===

$85604588212035* 搭建电路，计算输入中前导零的个数



=== campaign/counter/hint_0.txt ===

$74290091312759* 要通过这一关，只需要在之前实现的可擦写存储器上稍作调整即可。



=== campaign/counter/hint_solution.txt ===

$22938387275450* 你只需要在延迟线后方反向接回到自身输入时将其中的值加一即可。

$81327009436542* 你可以直接使用加法器，不过这有些杀鸡用牛刀了。



=== campaign/counter/label.txt ===

$24866509692444* 步进/覆写



=== campaign/counter/meta.txt ===

$42949183679479*
搭建一个计数器。每个时钟周期结束时，其中存储的数值都会自动加 1。

此外，计数器还应有一个擦写功能，允许使用输入的数值覆盖计数器内存储的数值。

本关有两个输入端：一个 1 位输入，一个单字节（8 位）输入。

1 位的输入端用于切换步进模式和擦写模式，单字节的输入端则用于指定要写入的数值。

$51274378991709* 计数是一种昆虫也具备的能力。拥有计数能力的生物才能进一步演化，发展出比较和算术的能力。这样一来，不知不觉间，裸猿也能造出计算机了。

$68850421394935* 计数器



=== campaign/counter/test.si ===

$27837193789838* 输出应为 {memory}。

$30050502504940* 计数器步进

$69821998974515* 用 {num} 覆写计数器的值



=== campaign/counter/ui.txt ===

$16305942415014* 操作

$57018164959250* 下一刻预期输出



=== campaign/counting_signals/hint_0.txt ===

$20653200546136* 用于确定“输出 0”的电路和“奇数计数技术”这一关里的电路是相同的。

$39788606928520* 用于确定“输出 1”的电路和“成双成对”这一关里的电路基本相同，区别在于这一关里四路输入都为 [T] 时不输出 [T]。



=== campaign/counting_signals/hint_1.txt ===

$79041418443903* 用于确定“输出 0”的电路和“奇数计数技术”这一关里的电路是相同的。



=== campaign/counting_signals/hint_2.txt ===

$90442785399123* “输出 2”只在所有输入均为 [T] 时为 [T]。



=== campaign/counting_signals/hint_3.txt ===

$12139411441713* “输出 1”在不少于 2 路输入为 [T] 时为 [T]，但 4 路输入均为 [T] 时例外。

$83417330967064* 我们已经在“成双成对”这一关中实现了前半部分。



=== campaign/counting_signals/meta.txt ===

$14499217305520* 信号计数

$83123268362253*
本关里你要实现的电路是一个二进制计数器，它的三个输出引脚分别对应 1、2、4 三个二进制数位。
你需要计算四路输入里有多少路处于 [T]，并将结果转换成二进制，发送到输出端的三个引脚上。

[tip]此关卡的解法不很简洁，你需要用到比前几关里更多的元件。[/tip]



=== campaign/decoder_1/meta.txt ===

$55345008240214* 二进制译码

$64947954189801* 搭建一个电路，根据输入信号，在 2 路输出中选择一路输出 [T]。



=== campaign/decoder_1/ui.txt ===

$40303102766749* 输出 0

$56552908891774* 输出 1



=== campaign/decoder_2/meta.txt ===

$44276233109848* 2-4 译码器

$46223188985873* 存在两路输入时，输入信号共有 4 种组合。请搭建电路，根据输入，在 4 路输出中选择一路，输出 [T]。注意其余三路输出必须同时输出低电平 [F]。



=== campaign/decoder_3/label.txt ===

$44918705544255* 禁用



=== campaign/decoder_3/meta.txt ===

$28695849165746* 当我们输入 3 位信号时，可能的取值共有 8 种。请搭建电路，根据输入，在 8 路输出中选择一路，输出 [T]。注意其余七路输出必须同时输出低电平 [F]。和之前的译码器关卡不同，这一关我们还要为译码器元件添加一个“禁用”引脚。当这个引脚使能（[T]）时，所有输出都必须是 [F]。

$43603044118584* 3-8 译码器



=== campaign/decoder_3/test.si ===

$10870388349665* 预期仅有第 {cycle} 路输出高电平 [T]，其余各路则输出低电平 [F]。

$18073111523064* 所有输出都应为低电平 [F]，因为禁用位已被激活。



=== campaign/decoder_3/ui.txt ===

$20191487800946* 期望激活线路

$23128720321555* 禁用

$23707304171214* 注意确保禁用位为 [T] 时，各路输出都为 [F]。



=== campaign/dependency/hint_0.txt ===

$21613887420121* 此处是一个简单的的循环非门：它的输入取决于自身的输出。

$57091568089512* 请特别留意红色标出的问题线路。

$64834808154176* 这在其他关卡中是错误的，不过本关里，这是你需要实现的目标。



=== campaign/dependency/hint_1.txt ===

$13967626449720* 有些情况下（比如上方的例子），循环依赖甚至可能很有欺骗性，其中的逻辑关系看似正确，但实质上是循环依赖的。

$71118235828147* 循环依赖有时会很复杂，牵涉许多的线路和组件。



=== campaign/dependency/meta.txt ===

$24156270270079*
这一关的任务是搭建一个“循环依赖”的电路。这个电路的输入依赖于它自身的输出。当发生循环依赖时，我们可能会很难确定元件产生的输出，因为你需要首先确定输入是怎样的，但要确定输入又需要先确定元件的输出，……所谓“循环”指的就是这种套娃式的依赖关系。

这种状态在其它所有关卡中都是不允许出现的，只有本关例外。本关的目标恰是需要你构造这样一个电路，这样你在进入下一关以前就会对这一情形有更深入的了解。

$25862237357880* 循环依赖

$57043666310618* 我不清楚这对学生有没有好处，但老师们都很喜欢这么做。

$60783049086609* 在我们的教育系统中，传统的教学方式是骗学生走错误的路，然后对他们发出大声嘲笑。



=== campaign/double_buffer/meta.txt ===

$28070798445412* 你需要搭建一个电路，将输入延迟 2 周期后输出。

$66914768639545* 本关引入了延迟线元件。它接受一个输入后，会延迟 1 周期将其输出。

$81657957055974* 晚点到站



=== campaign/double_number/hint_0.txt ===

$13944257184132* 本关里，我们需要处理一个字节（byte），这是每组共 8 个二进制位的信号。我们必须通过分线与集线来对它进行操作。

$16215081868720* 到此前为止，我们都只接触过单个二进制位（bit）的运算，它只涉及一个信号的高/低电平（[T]/[F]），即通断状态。



=== campaign/double_number/hint_1.txt ===

$29000872588470* 在二进制中，要将一个整数翻倍，你只需要将它的所有二进制位向高位方向移动一位。



=== campaign/double_number/meta.txt ===

$46697878992908* 超级加倍

$78449227663032*
本关里，我们将引入单字节（byte）的信号。一个字节可表示一个 0 ~ 255 之间的整数。每个字节都由 8 个二进制位（bit）组成。在本关中，你将获得两个新的元件，第一个是分线器，它能将一条单字节导线（8 位线）分割成八条 1 位导线；第二个是集线器，其功能恰好相反。

你需要利用这些元件，找到一种让输入翻倍的方法（本关输入范围为 0 ~ 127 的整数）。



=== campaign/foundry/meta.txt ===

$24718289227251*
欢迎来到元件工坊。在此创建的电路可以在其他关卡中作为自定义元件直接调用。
自定义元件的功能和外形取决于你在此设计的电路的具体结构和布局。

$62612312608874* 本关并不是一个挑战关卡，而是一个工具性关卡。你随时可以回到关卡树界面，继续完成后续关卡。

$72171231322685* 元件工坊

$88436914545275* 在“切换电路图”菜单中，你可以添加、删除自定义元件，也可以重命名已创建的元件。



=== campaign/full_adder/hint_0.txt ===

$50970897346580* 求总和位（SUM）的思路与“奇数计数技术”这一关类似。



=== campaign/full_adder/hint_1.txt ===

$54848313056941* 进位（CARRY）仅在至少两路输入为 [T] 时为 [T]。



=== campaign/full_adder/hint_solution.txt ===

$13880107359455* 请自行探索更好的解法吧！

$18497022543669* 这种解法不是最优雅或者最高效的。



=== campaign/full_adder/label.txt ===

$12555311310864* 输入 0

$13755587162128* 输入 2

$34717193596171* 进位

$41149959264274* 输入 1

$50183740481245* 总和



=== campaign/full_adder/meta.txt ===

$34381936755276*
上一关里，我们对两路输入进行了求和。这一关里我们对三路输入求和。和上一关相同，请对三路输入作二进制加法，使输出总和位（SUM）为 [b]0[/b] 或 [b]1[/b]。

与普通加法一样，如果结果不能用一位数来表示，将进位数（CARRY）设为 [b]1[/b]。

$42735906141201* 全加器



=== campaign/full_adder/ui.txt ===

$40317306745068* 预期总和

$49855734765642* 预期进位

$51965136043073* 当前进位

$84617036256734* 当前总和



=== campaign/hex_racer/meta.txt ===

$11327399415058* 这一关是我第二喜欢的消遣小游戏。你需要在有限的时间内将十六进制数手动转换为二进制。

$45399195121692* 十六进制速算

$65517909958697*
当数位很多时，二进制数的可读性会变差，十六进制（hexadecimal）则会更加简明易读。十六进制下，每个数位代表 4 个二进制位：

0 [F][F][F][F]
1 [F][F][F][T]
2 [F][F][T][F]
3 [F][F][T][T]
4 [F][T][F][F]
5 [F][T][F][T]
6 [F][T][T][F]
7 [F][T][T][T]
8 [T][F][F][F]
9 [T][F][F][T]
A [T][F][T][F]
B [T][F][T][T]
C [T][T][F][F]
D [T][T][F][T]
E [T][T][T][F]
F [T][T][T][T]

下面我们举一个例子，来说明十六进制数更加简明。让我们看看最大的 16 位二进制数在不同进制下是怎样表示的：
[left]
                二进制  ： 1111111111111111
                十进制  ： 65535
                十六进制： FFFF
[/left]
在十进制和二进制的转换中，想要发现数位丢失或者写错数值等错误是很难的。但是只要你对十六进制数足够熟悉，在十六进制和二进制的转换中，类似的问题是很容易定位的。

$87098190175913*
点击下方面板的数位可以将其反转。你需要让高电平 [T] 数位的总和恰好等于给定的十六进制数值。

为通过本关，你至少需要连续通过 3 级。



=== campaign/introduction/meta.txt ===

$26182817405385*
恭喜恭喜，你被绑架了！

我们即将在飞船上对你进行一系列智力测试。

你只需要制造一台能用的电脑，就能为你的种群赢取正式加入星系联邦的机会。

$44716420394020* 从零开始

$76679675871478* 第一项测试检验你是否能够理解与电路有关的知识。关卡中的电路包含一个输入端口、一个输出端口，还有一根将它们连在一起的导线。你需要拨动左侧菜单中的开关来完成这一关。



=== campaign/logic_gate_racer/meta.txt ===

$35186537961257* 这一关的目的是在进入后续关卡之前，验证你是否真的已经掌握了基础布尔运算的规则。这对你顺利解决后续的问题是很有必要的。

$39180730338379*
你需要在此针对几个给定的真值表依次构造对应的电路。点击左侧菜单里的“快速运行”按钮后，程序就会自动验证测例。如果你的电路通过了给定真值表的全部测例，此次测试结果就会标为 [T]，否则会被标为 [F]。要通过这一关，你至少要获得四个通过标记（[T]）。

（注意，在这一关里，你只能使用一部分已解锁的逻辑门。——译注）

$39721874026332* 干得漂亮。既然你已经对基础的逻辑运算有了足够的理解，接下来就让我们开始逐步搭建属于你自己的电脑吧。不过在真正涉及计算机架构之前，你首先还得具备数据存储和二进制算术的相关知识。

$57679157572023* 逻辑试炼



=== campaign/logic_gate_racer/ui.txt ===

$32183772878666* 测验结果



=== campaign/maze/hint_0.txt ===

$10423837492124* [left][b]原地左转[/b][/left]

$18756407685566* [left][b]如果面前是墙，原地右转；重复这一步，直到面前不是墙壁为止[/b][/left]

$51767168505953* [left][b]返回第一步并重复上述操作[/b][/left]

$60076150664554* 如果你始终沿着左手边（或右手边）走，那么你最终一定能到达出口。

$63325960964451* [left][b]前进一步[/b][/left]

$66501964970865* 下面是这种解法的伪代码：



=== campaign/maze/meta.txt ===

$19088384441761*
你可以通过读取输入判断机器人面对的那一格是什么东西。输入只能取得下列数值之一：
0 通路
1 墙壁


$56722492138232* 做得好！现在你已经可以称得上是 Overture 架构的汇编高手了。不过再怎么说，Overture 架构也只是入门级的电脑，它是一个很好的教具，不过从实用角度讲，它还是缺少了很多重要的功能和部件。接下来，我们会教你搭建一个叫做 Symphony 的计算机架构。这台计算机比 Overture 强大得多，它带有内存、显示屏和键盘，并且允许你使用函数式编程。当然，在此之前，你首先还是需要花一些时间为这台新电脑准备必要的元件，并了解诸如栈之类的更复杂的概念。

$84960209408475*
本关里，你将通过输出组件控制一个机器人。请编写一段程序，实现让机器人走出迷宫的算法。

向机器人输出的控制命令如下：
0 原地左转
1 前进一格
2 原地右转

你也可以先试试使用方向键手动控制机器人，体会一下机器人是如何运动的。

$90660848232877* 路在脚下



=== campaign/mod_4/hint_0.txt ===

$23027113131109* 数字的最低 1 位代表 2 的模数，最低 3 位代表 8 的模数，等等。

$35037773638556* 类似地，在十进制数 4321 中，要得到 100 的模数也很简单。

$40190253854900* 在二进制中，一个数字对 4 取模等价于仅取用两个最低位。

$44666331884152* 这是因为更高位（表示 4、8、16 等）除以 4 没有余数。

$47075416850998* 一般而言，对于 2 的正整数幂作除数的情况，这种余数与最低位的关系都成立。

$79521133202800* 答案是 21，忽略百位及以上的数字即可，因为 100 是 10 的幂。

$81555476661504* 现在，只要弄清楚如何提取一个数字的最后两位，你就能通过这一关。



=== campaign/mod_4/meta.txt ===

$46388374967041*
本关里，你需要从输入端读取一个整数，并输出这个数除以 4 的余数（对 4 取模）。

本关的难点在于，计算用时不得超过 8 个时钟周期。

注意：你不需要对硬件作任何改动。只要找到快速进行模 4 计算的技巧即可。

$71000564779980*
我们的一个星期有 4 天，分别是零之日，壹之日，贰之日和叁之日。我听说一些地球人会把贰之日的日子算错？
  
不过这倒是没什么好惊讶的。

$76392666043520* 不管怎么说，新的一年要开始了，我们想让你来算算每个人的生日都是几之日。我们会给你的电脑输入一些日期，你则需要在 8 周期之内输出这是一个星期中的第几天。

$78836302049950* 高速掩码



=== campaign/mod_4/test.si ===

$13853243145042* 你必须在第 8 周期前输出结果！

$59240995307159* 你需要先读取输入。

$60992625993288* {inp} mod 4 结果应为 {result}。



=== campaign/multiply/meta.txt ===

$44500958231665* 搭建一个电路，将两路 8 位输入相乘后输出。结果里超出 8 位的部分直接舍弃即可。

$54529139494347* 乘法器



=== campaign/multiply/test.si ===

$13790051293386* {a} * {b} = {result}

$46804407616321* {a} * {b} 的最低八位为 {result}

$83214947196979* 将两路输入相乘



=== campaign/multiply/ui.txt ===

$77112891598455* 将两路输入相乘



=== campaign/nand_gate/meta.txt ===

$36846418389807* 地球上所有的动物眼下都在接受相同的测试，以确认这颗星球上是否有哪种生物真的有搭建一台电脑所需的智力。

$39082333495604* 与非门（NAND）

$50880631203389* 正确！你已经解锁了与非门。从这个元件出发，你会亲手搭建出这台电脑里其它的一切东西。

$65167079914703* 第一部分测试的主题是“布尔代数”。布尔代数是对单个二进制位（bit）的基础运算。这些运算是构成计算机科学中一切其他操作的基本元素。

$68865507501612* 这个电路里有一个“与非门”（NAND gate），你需要仔细研究它，然后通过填写下面面板中的“真值表”（truth table）来描述它的行为。真值表中只有“输入”这两行是填好的。你的任务是通过尝试调整电路的输入，观察与非门做了什么，然后将真/假（[T]/[F]）填入真值表的最后一行（输出值）。



=== campaign/negative_numbers/meta.txt ===

$16731935541997*
本关里，你需要练习如何用“补码”表示负整数，这是二进制系统里负数最常用的表示方法。
  
在补码表示法中，最高位的数字是负数。对于单字节数据而言，这意味着最高位（第 8 位）代表的数值从 128 变成了 -128。

要通过本关，你的成绩至少需要达到 3 级（即至少通过前两级）。

$20753698232132* 负数

$87951492143019* 要知道事物之间的差异，你就要做减法。而要想做减法，你得先会写负数。



=== campaign/nim/meta.txt ===

$19817843844200* 尼姆博弈

$47072576894526* 此外，在汇编关卡中，你可以调用先前已经搭建的任意一种计算机架构。换言之，你既可以用 Symphony 架构解决本关的任务，也可以使用 Overture 架构。单击界面左上角的“切换电路图”按钮即可选择你想要使用的架构电路。

$53912339443439*
本关里，你需要在一场简单的纸牌游戏中击败我们的 AI 对手。游戏的规则如下：

牌桌上共有 12 张牌，你和对手需要轮流从牌桌上取走纸牌。每个人每次只能取走 1 至 3 张纸牌，且不能跳过自己的回合。游戏开始时，你先取牌。取走最后一张牌（鬼牌）的一方失败。

你可以随时从输入端读取当前牌桌上剩余的纸牌数量。向输出端发送 1 ~ 3 的数值可以取走对应数量的纸牌。你的对手会在你出手后立刻行动，所以你可以在输出数值后立刻读取输入，来获取对手操作之后的牌桌情况。



=== campaign/nim/test.si ===

$27262056315410* 你输了！

$29769682738867* 一次只能取 1 ~ 3 张牌。

$42147812867053* 你赢了！

$49299754864790* 按下回车键以取走 {card_count} 张牌

$64085588225039* 按下回车键以显示对手操作后的结果

$85502688597126* 按下方向键以选择要取走的牌

$90440029783715* 你取走了最后一张牌，你输了！



=== campaign/nim/ui.txt ===

$79378464416004* 按下方向键以选择要取走的牌



=== campaign/nor_gate/hint_0.txt ===

$18962231551900* 在输入上接入非门，得到的结果就是“这路输入是否为 [F]”。

$68908249643417* 由真值表可知，或非门仅在两路输入都为 [F] 时输出 [T]。



=== campaign/nor_gate/hint_1.txt ===

$14349743750598* 这样一来问题就变成了如何实现与门，或者“非”“与非”（NOT-NAND）门。



=== campaign/nor_gate/meta.txt ===

$37240300421781*
地球上的大多数生物都是脾气暴躁又三心二意的野蛮物种。

要想成功通过测试，你就需要管理自己的破坏本能，多用逻辑来思考问题。

$56653221050913* 这一关里，你需要搭建一个与给定的真值表匹配的电路。

$72918877035793* 或非门（NOR）



=== campaign/not_gate/hint_0.txt ===

$26513163439009* 目前唯一可用的元件就是与非门



=== campaign/not_gate/hint_1.txt ===

$20946507323050* 当两路输入都为 [T] 时，输出为 [F]。

$88952480145102* 当两路输入都为 [F] 时，输出为 [T]。



=== campaign/not_gate/meta.txt ===

$16394937100308* 非门（NOT）

$56423993638708* 上一关里，你填写了描述给定电路的真值表。在这一关，你需要搭建一个与给定的真值表匹配的电路。

$64052600264884*
请使用与非门，实现非门（NOT gate）的功能。
可用元件：与非门（NAND）
输入 0：[F][T][F][T]
输入 1：[F][F][T][T]
输出：  [T][T][T][F]

搭建目标：非门（NOT）
输入：  [T][F]
输出：  [F][T]

$80163590000700* 既然你已经解锁了与非门，那么是时候自己动手搭建一个电路了。



=== campaign/odd_number_of_signals/hint_0.txt ===

$17243045715726* 你可以只用 1 个组件判断两路输入中是否有奇数个 [T]。



=== campaign/odd_number_of_signals/hint_1.txt ===

$39747324204871* 但如果我们把它们看作偶数（0）/ 奇数（1）呢？

$80670337048058* 到目前为止，红色信号 [F] 被称为假（低电平），绿色信号 [T] 被称为真（高电平）



=== campaign/odd_number_of_signals/hint_2.txt ===

$28104365880572* 偶数 + 偶数 = 偶数

$49444546097133* 奇数 + 奇数 = 偶数

$57603105454008* 现在，我们是否有一个组件能模拟这种行为？

$59534613718377* 奇数 + 偶数 = 奇数



=== campaign/odd_number_of_signals/hint_3.txt ===

$47175212977659* 可以看出，异或门正是我们需要的东西。



=== campaign/odd_number_of_signals/meta.txt ===

$44190469254011* 奇数计数技术

$63242509760527* 用不超过 3 个元件搭建电路。仅在输入中为 [T] 的数量为奇数时输出 [T]。



=== campaign/odd_number_of_signals/test.si ===

$36609687959808* {count} / 3

$40553112323959* 本关里你只能使用至多 3 个元件。



=== campaign/odd_number_of_signals/ui.txt ===

$74552564780850* 已使用组件



=== campaign/odd_ticks/hint_0.txt ===

$69947751578736* 这一关的输入只是用来干扰你的！

$75667038547709* 真正有用的信息来自当前的时钟周期数，用延迟线来获取这个与时间相关的信息吧。



=== campaign/odd_ticks/hint_1.txt ===

$14188568517859* 延迟线的输出端可以接回自身的输入端，

$88356074900046* 用这种接法可以制造一个与时钟周期相关的振荡信号。



=== campaign/odd_ticks/meta.txt ===

$17699211754487* 上一关里，你已经知道了我们不允许电路中存在循环依赖。现在你需要掌握一种例外情况。

$54648226811178* 奇变偶不变

$60625429879527*
电路中橙色引脚的输入不会影响同一时钟周期的输出值，因此，这种引脚不会造成循环依赖。
  
  [image="delay_line.png"]

$75292456030647*
新元件“延迟线”的输入端可以与自身的输出端直接相连。这是因为这个元件当前的输入信号直到下一个时钟周期才会对电路其它部分产生影响。
  
[image="delay_line.png"]

$85913836277587* 请设计电路，在偶数周期输出 [F] ，奇数周期输出 [T] 。



=== campaign/one_hot_encoding/hint_0.txt ===

$28460985244857* 你需要的元件主要是一个移位器



=== campaign/one_hot_encoding/hint_1.txt ===

$49063245216494* 这一关里，你要用到早先解锁的逻辑左移器（LSL）



=== campaign/one_hot_encoding/meta.txt ===

$12296593054599* 独热编码

$17817215316423*
本关里，你的电路要根据输入的数值，将对应的一路输出置为 [T]。输出端的索引从 0 开始，因此需要激活的是第 N + 1 路输出。例如，如果输入的值为 7，那你需要将第 8 路输出置为 [T] ，其它输出置为 [F]。

本关的限制是，你最多只能使用 3 个元件。另外，你也不能使用之前解锁的译码器。



=== campaign/one_hot_encoding/test.si ===

$60812617177494* 你只能使用不超过 3 个元件。

$74562193652628* 第 {pin} 路输出的结果有误。



=== campaign/or_gate/hint_0.txt ===

$29061908449874* 输出就会是 [T]。

$49190016957852* 从或门的真值表可以看出，只要有一路输入是 [T]，



=== campaign/or_gate/meta.txt ===

$46797361496226*
请搭建与给定真值表对应的电路。
[tip]双击一个元件后拖动，即可将它与相连的导线一起移动。[/tip]
  

$81822607191994* 或门（OR）



=== campaign/or_gate_3/hint_0.txt ===

$67313804184537* 更大的或门其实就是多个或门首尾相接。



=== campaign/or_gate_3/meta.txt ===

$29275887429601* 搭建一个拥有三路输入的或门（OR）。

$68089739910654* 三路或门



=== campaign/or_gate_3/ui.txt ===

$15378963142694* 输入 2



=== campaign/overture_1_registers/default.isa ===

$58396790216558* 将 %b 中的数值写入 %a。



=== campaign/overture_1_registers/hint_0.txt ===

$25938996008186* 唯一的区别就是我们需要用给定的源代替输入端子，用给定的目标来代替输出端子。

$87908319845833* 这一关的思路与“总线”一关类似。



=== campaign/overture_1_registers/hint_1.txt ===

$66937784075495* 我们可以使用译码器来指定要启用的源和目标。



=== campaign/overture_1_registers/meta.txt ===

$13757092116124*
[color=#ff6680]源[/color]和[color=#e49f44]目标[/color]可以是六个寄存器中的任意一个，对应编号从 0 号寄存器（REG 0）到 5 号寄存器（REG 5）为止。
  
除此之外，本关自带一个输入元件和一个输出元件，它们分别可以作为[color=#ff6680]源[/color]和[color=#e49f44]目标[/color]使用。

$36376879506769* 是时候开始你的主线项目了。从现在开始，一步步搭建 [color=#e49f44]Overture[/color] 计算机架构吧。它是一台图灵完备的机器，是当之无愧的计算机！

$61875924861326*
本关里，你需要搭建一个电路，使之能够将数据从[color=#ff6680]源[/color]复制到[color=#e49f44]目标[/color]。

这一关中，指令字节中的某些二进制位将指定[color=#ff6680]源[/color]和[color=#e49f44]目标[/color]寄存器。

其中，第 0、1、2 位指定[color=#ff6680]源[/color]。第 3、4、5 位指定[color=#e49f44]目标[/color]。

$79626649565563* 川流不息

$87179643828952*
以下两表分别给出了指令中的[color=#ff6680]源[/color]及[color=#e49f44]目标[/color]所指代的存储位置：

[color=#ff6680]源[/color]:
[left]
                [F] [F] [F]  REG 0（0 号寄存器）
                [F] [F] [T]  REG 1（1 号寄存器）
                [F] [T] [F]  REG 2（2 号寄存器）
                [F] [T] [T]  REG 3（3 号寄存器）
                [T] [F] [F]  REG 4（4 号寄存器）
                [T] [F] [T]  REG 5（5 号寄存器）
                [T] [T] [F]  #INPUT（输入组件）
                [T] [T] [T]  UNUSED（未使用）
[/left]

[color=#e49f44]目标[/color]:
[left]
                [F] [F] [F]  REG 0（0 号寄存器）
                [F] [F] [T]  REG 1（1 号寄存器）
                [F] [T] [F]  REG 2（2 号寄存器）
                [F] [T] [T]  REG 3（3 号寄存器）
                [T] [F] [F]  REG 4（4 号寄存器）
                [T] [F] [T]  REG 5（5 号寄存器）
                [T] [T] [F]  #OUTPUT（输出组件）
                [T] [T] [T]  UNUSED（未使用）
[/left]



=== campaign/overture_1_registers/test.si ===

$18540192543555* 寄存器 {reg_i} 的值应为 {value}。

$51132330915663* 输出未启用。

$75546240775660* 预期输出为 {value}。

$85392755740261* 输出不应处于“启用”状态。



=== campaign/overture_1_registers/ui.txt ===

$77115196290575* 搭建可以按照指令读写寄存器的电路



=== campaign/overture_2_alu/default.isa ===

$57911760722636* 将 %b 中的数值写入 %a。



=== campaign/overture_2_alu/meta.txt ===

$17602708328746*
是时候将你在“算术逻辑单元”一关里实现的计算单元加入我们的计算机架构中了。你之前搭建的电路已被保存到了元件工坊中，你可以直接将它作为一个自定义元件，添加到本关的电路里。如果你记不清每个引脚分别都是什么功能了，只需回到元件工坊中，重新查看电路图即可。

你可以用一个译码器来确定计算机当前是在哪种模式下工作。四种工作模式重述如下：
[left]
                [F][F] 立即数模式（Immediate）
                [F][T] 运算模式（ALU）
                [T][F] 复制模式（Move）
                [T][T] 条件跳转模式（Condition）
[/left]

本关里，你暂时只需要实现中间两种模式，即复制模式和运算模式。在运算模式下，你的电脑需要将[color=#e49f44]REG 1[/color]（1 号寄存器）和[color=#e49f44]REG 2[/color]（2 号寄存器）作为输入进行运算，并将运算结果存入[color=#e49f44]REG 3[/color]（3 号寄存器）。

[tip]别忘了你的 3-8 译码器有一个“禁用”位，可以屏蔽所有输出。[/tip]

$76398546711745* 计算核心



=== campaign/overture_2_alu/test.si ===

$27417572090527* 输出未启用。

$45837083894306* 预期输出为 {value}。

$67011612338355* 寄存器 {reg_i} 的值应为 {value}。

$84026509534190* 输出不应处于“启用”状态。



=== campaign/overture_2_alu/ui.txt ===

$49706182840588* 向电路中添加 ALU



=== campaign/overture_3_immediates/default.isa ===

$50864238070873* 将 %b 中的数值写入 %a。



=== campaign/overture_3_immediates/meta.txt ===

$23614311904581* 立即数

$63109056149876*
我们需要一种手段直接从程序代码中提取一个数，并将其送入寄存器中。为了实现这一点，当指令的最高两位为 [F][F] 时，我们要让计算机切换到立即数（Immediate）模式。

在立即数模式下，整个指令字节将被视为一个纯数字，它将被写入 0 号寄存器（REG 0）中。这意味着我们可以直接从程序代码中将 0 到 63 之间的字面值写入寄存器。



=== campaign/overture_3_immediates/test.si ===

$17793323757435* 预期输出为 {value}。

$63497936956369* 输出不应处于“启用”状态。

$73489311755739* 寄存器 {reg_i} 的值应为 {value}。

$82564442776805* 输出未启用。



=== campaign/overture_3_immediates/ui.txt ===

$57764930098721* 向电路添加立即数模式



=== campaign/overture_4_program/default.isa ===

$26930827349244* 将 %b 中的数值写入 %a。



=== campaign/overture_4_program/meta.txt ===

$10102035559374* 程序

$58149108600515* 指令输入组件已经被移除，从这一关开始，我们使用包含一段程序的内存（RAM）组件来替换它。这是一个带读取端口的存储器。当读取端口启用时，它会向输出引脚发送 RAM 中指定地址的数据。请使用计数器元件，让你的电路在每个周期从程序存储器中自动读取下一条指令。这个计数器称作程序计数器（program counter，缩写为 PC）。



=== campaign/overture_4_program/test.si ===

$19443898128380* 输出不应处于“启用”状态。

$49097812105667* 寄存器 {reg_i} 的值应为 {value}。

$50052313044113* 输出未启用。

$73023200204536* 计数器的值应为 {expected_value}。

$88140381331491* 预期输出为 {value}。



=== campaign/overture_4_program/ui.txt ===

$62678678871254* 将程序存储器和程序计数器整合进电路中



=== campaign/overture_5_conditionals/label.txt ===

$37075142107851* Reg 2

$38743609381557* Reg 1

$40362507068221* Reg 4

$57061942907076* Reg 5

$79357977314471* Reg 3

$82470056393191* Reg 0



=== campaign/overture_5_conditionals/meta.txt ===

$27747401844990* 你成功了，地球人！我原来以为你只是一只奇怪的裸猿，但你已经从零开始搭建出了一台真正的电脑！干得不错。

$59169726539090* 图灵完备

$77166984247940* 到目前为止，我们所有的程序都只能逐字节顺序执行。

$85320707451673* 在之前的关卡中，只有代码能影响数据，现在是时候让数据来影响代码运行了。添加了条件跳转的能力后，我们的电脑就能运行任何算法，完成一切可行的计算了。和现实中其它的所有计算机一样，这台电脑的计算能力只会受到它有限的存储容量的制约。

$89085328104477*
我们最后要完成的一项任务，是实现一种通过指令控制程序计数器的手段，在满足指定的条件时，让我们的程序跳转到任意位置执行。

当指令的最高两位被置为 [T][T] 时，计算机应进入条件跳转模式。在该模式下，我们将判断 3 号寄存器（REG 3）中的数值是否满足指令中最低的 3 位所指定的条件。如果满足该条件，我们就用 0 号寄存器（REG 0）中的值来覆盖程序计数器的数值。
这个操作允许我们在指定条件下改写程序计数器，从而在特定情况下跳过某些指令，或反复运行同一组指令。

跳转条件的类型如下：
[left]
                [F][F][F] Never（必不跳转）
                [F][F][T] Always（必定跳转）
                [F][T][F] [color=#e49f44]REG 3[/color] = 0 时跳转
                [F][T][T] [color=#e49f44]REG 3[/color] ≠ 0 时跳转
                [T][F][F] [color=#e49f44]REG 3[/color] < 0 时跳转
                [T][F][T] [color=#e49f44]REG 3[/color] ≥ 0 时跳转
                [T][T][F] [color=#e49f44]REG 3[/color] ≤ 0 时跳转
                [T][T][T] [color=#e49f44]REG 3[/color] > 0 时跳转
[/left]

上述条件与已经保存在元件工坊中的条件判断组件（COND）的输出是一致的。



=== campaign/overture_5_conditionals/test.si ===

$17521915837347* 输出不应处于“启用”状态。

$33411257451562* 预期输出为 {value}。

$36308361121667* 输出未启用。



=== campaign/overture_5_conditionals/ui.txt ===

$65145204616501* 向电路添加条件跳转功能



=== campaign/overture_6_budget/default.isa ===

$18505654344513* 无条件跳转至寄存器 r0 的值对应的地址。

$21095867785396* 对寄存器 r1 和 r2 的值执行按位与运算，并将结果存入寄存器 r3。

$24147817394058* 当寄存器 r3 的值小于 0 时，跳转至寄存器 r0 的值对应的地址。

$26704206992933* 对寄存器 r1 和 r2 的值执行按位与非运算，并将结果存入寄存器 r3。

$33850592701591* 将寄存器 r1 和 r2 的值相减，并将结果存入寄存器 r3。

$42577908074742* 将固定值 %a 写入寄存器 r0。

$43876958520450* 当寄存器 r3 的值不等于 0 时，跳转至寄存器 r0 的值对应的地址。

$45432635426071* 将 %b 中的数值写入 %a。

$46599288949396* 当寄存器 r3 的值等于 0 时，跳转至寄存器 r0 的值对应的地址。

$48758564562305* 当寄存器 r3 的值小于等于 0 时，跳转至寄存器 r0 的值对应的地址。

$58823897430160* 对寄存器 r1 和 r2 的值执行按位或运算，并将结果存入寄存器 r3。

$64808551937719* 当寄存器 r3 的值大于等于 0 时，跳转至寄存器 r0 的值对应的地址。

$71072332861445* 不执行任何操作。

$75067212691206* 对寄存器 r1 和 r2 的值执行按位或非运算，并将结果存入寄存器 r3。

$75524550463342* 将寄存器 r1 和 r2 的值相加，并将结果存入寄存器 r3。

$88048573834702* 当寄存器 r3 的值大于 0 时，跳转至寄存器 r0 的值对应的地址。



=== campaign/overture_6_budget/label.txt ===

$15531830527231* Reg 3

$17025449350330* Reg 5

$42538649427331* 程序

$47858891143005* Reg 2

$57877356797542* 已执行指令数

$59383212597903* Reg 0

$76878335565401* Reg 4

$78214997465973* 计数值

$89909032864119* Reg 1



=== campaign/overture_6_budget/meta.txt ===

$35331465118106* 轻快序曲

$59797408403606*
本关卡是一个可选关卡，其用意在于为你提供一个用于进一步优化 Overture 架构性能的试验环境。与之前的关卡不同，这一关里，你的计算机每周期可以执行多于或少于一条的指令。
  

$59818810946218* 默认设置下，本关卡的验证系统只检查电脑的输出值是否与预期结果相符。不过，你也可以选择对寄存器的状态进行额外校验，这有助于你开展调试工作。是否校验寄存器的选择权完全在你。若你希望校验寄存器，那么你需要在每个时钟周期向“已执行指令数”这个输出端发送本周期内执行完毕的指令数量。

$84590049728141* 注意，你可以将内存组件的类型由 SRAM 改为 DRAM。这么做会大幅提高内存的延迟量，同时极大地减少其中使用的逻辑门数量。不过，对于 DRAM 内存，你可以设置它的流水线深度，增加它的读取周期，即将数据延迟分摊到多个周期内，从而降低每周期内的延迟量。例如，流水线深度为 2 时，DRAM 内存将在两周期后响应当前的请求（即共花费 3 周期完成），与此同时，其延迟量也会降为三分之一。



=== campaign/overture_6_budget/test.si ===

$24524168624111* 计数器的值应为 {expected_value}。

$35224907301551* 寄存器 {reg_i} 的值应为 {value}。

$45858569181521* 你读取了 {.input_index} 次输入，但预期的读取次数为 {.emulator_input_index}。



=== campaign/overture_6_budget/ui.txt ===

$22306447815263* 优化 Overture 架构的性能



=== campaign/overture_alu_1/hint_0.txt ===

$17808301775724* 这一关和“数据选择器”非常类似。

$69085851994491* 我们需要用与非、或、与、或非的运算结果代替原先的输入 A/B。



=== campaign/overture_alu_1/hint_solution.txt ===

$76898193108851* 用一个译码器就可以确定我们要开启哪个开关。



=== campaign/overture_alu_1/meta.txt ===

$16562043259074* 逻辑整合

$31234606133949*
搭建一个电路，对输入的两个字节执行按位与/或/与非/或非操作。第一路的 2 位输入是一个操作码（OpCode）。操作码是一个整数，用于指定我们要进行哪种计算。

操作码列表：

[color=#87a8c8]0 NAND（按位与非）
1 OR（按位或）
2 AND（按位与）
3 NOR（按位或非）[/color]



=== campaign/overture_alu_2/hint_solution.txt ===

$30599543511275* 我们用3-8译码器代替2-4译码器，实现功能扩充。

$61118397217284* 注意，A 减 B（A SUB B）即为 A 加负 B（A ADD (NEG B)）。



=== campaign/overture_alu_2/meta.txt ===

$20519420764551* 算术逻辑单元

$39134024311972*
向你的电路中加入加法和减法功能，实现算术逻辑单元（ALU）。

操作码列表：

[color=#87a8c8]0 NAND（按位与非）
1 OR（按位或）
2 AND（按位与）
3 NOR（按位或非）
4 ADD（加法）
5 SUB（减法）[/color]



=== campaign/overture_alu_2/ui.txt ===

$53936374688885* 操作码（Opcode）



=== campaign/overture_conditions/hint_0.txt ===

$30858693828450* 我们直接把这两种线路的输出端接到结果总线上。

$41615813866999* 从不成立/必定成立的情况很好处理。

$73479968135998* 判断数值是否等于零，实际上就是检查每一位是否都为 [F]。



=== campaign/overture_conditions/hint_1.txt ===

$71744044447857* 而要检验是否所有数位均为 [F]，我们只需要将每个二进制位分开，并将它们送入多路扇入的或非门即可。

$78036114842982* 下一步是判断输入值是否为负。



=== campaign/overture_conditions/hint_2.txt ===

$16809493892244* 要检验一个二进制数是否为负数，我们只需判断符号位是否为 [T] 即可

$70638453446538* 剩下的情况都可以由这三种情形经过简单的组合逻辑处理直接得出。



=== campaign/overture_conditions/hint_solution.txt ===

$19520914707885* [left]value ≥ 0 等价于 NOT (value < 0)[/left]

$44207156733924* [left]value ≤ 0 等价于 (value < 0) OR (value = 0)[/left]

$75072852663289* [left]value > 0 等价于 NOT (value ≤ 0)[/left]



=== campaign/overture_conditions/meta.txt ===

$71466914240996*
这个关卡的输入包括一个 8 位数值和一个 3 位的条件码。

条件码的含义如下表所示。你需要判断输入的数值是否满足给定条件，如果判断成立则输出 [T]，否则输出 [F]。

[left]
        条件码：     以下条件满足时，给出 [T]：
        [F][F][F]      Never（永不成立
        [F][F][T]      Always（必定成立）
        [F][T][F]      value = 0
        [F][T][T]      value ≠ 0
        [T][F][F]      value < 0
        [T][F][T]      value ≥ 0
        [T][T][F]      value ≤ 0
        [T][T][T]      value > 0
[/left]

$83283206082997* 条件判断



=== campaign/overture_conditions/test.si ===

$74974087807935* 必定成立

$80507287196650* 永不成立



=== campaign/overture_conditions/ui.txt ===

$11886599003881* value

$38979555213581* 条件描述

$43384041502940* 输入数值

$81487261104241* 条件码



=== campaign/overture_decoder/label.txt ===

$15645900189277* 复制模式

$60698949860454* 运算模式

$90597971391617* 立即数模式



=== campaign/overture_decoder/meta.txt ===

$44644153822563* 你在“川流不息”一关中搭建的电路可以在寄存器之间复制数值，而在“算术逻辑引擎”中搭建的电路可以对 2 路输入进行多种运算。在后续的关卡中，你需要在同一个电路中执行这两种不同的操作。要实现这一点，你需要搭建一个“指令译码器”。它能根据指令字节中我们尚未使用的那两位数值，来决定我们的计算机要在何种模式（MODE）下工作。

$62355105651643*
为了区分 4 种不同的指令，指令中最高的两位将被用来指定计算机的工作模式，如下所示：

[left]
                [F][F][Z][Z][Z][Z][Z][Z] Immediate：立即数模式
                [F][T][Z][Z][Z][Z][Z][Z] ALU：运算模式
                [T][F][Z][Z][Z][Z][Z][Z] Move：复制模式
                [T][T][Z][Z][Z][Z][Z][Z] Condition：条件跳转模式
[/left]
这里的 [Z] 意味着可以取任意一种状态。

根据输入确定我们要激活的模式（MODE），然后将相应的一路输出设为 [T]。

$81732613304305* 指令译码器



=== campaign/overture_decoder/test.si ===

$23393810721136* 运算模式（ALU）

$41856942338650* 条件跳转模式（Condition）

$67613074322431* 复制模式（Move）

$71705253055197* 立即数模式（Immediate）



=== campaign/overture_decoder/ui.txt ===

$35299017249605* 工作模式

$55162862394836* 指令



=== campaign/preview_architecture/meta.txt ===

$46932595269557* 架构预览



=== campaign/preview_foundry/meta.txt ===

$78694087261378* 元件预览



=== campaign/ram_component/hint_0.txt ===

$32597308066943* 首先，我们要向电路图中添加 4 个存储器。



=== campaign/ram_component/hint_1.txt ===

$73686127519870* 接下来我们要确定该读取/写入哪个存储器单元。

$86131527203527* 在这种场合，译码器是很好用的工具。



=== campaign/ram_component/hint_2.txt ===

$51243843817679* 通过译码器发送 [T] 信号，我们就能启用对应的存储单元。

$78963222298606* 别忘了用一个开关来控制输出，让它只在读取时接通。



=== campaign/ram_component/hint_3.txt ===

$51887730294248* 将它连接到存储器的输入引脚上。剩下的就是只在需要的时候激活存储器的写入功能。

$65959445914539* 要写入存储器的值来自输入端子。



=== campaign/ram_component/label.txt ===

$10655955073336* 读取

$46688176903674* 地址



=== campaign/ram_component/meta.txt ===

$14374127314134* 方寸之间

$68663841862704*
在本关中，你需要设计一个电路，令它能向 4 个 8 位寄存器中随意写入或从中读取信息。

输入的第一个信号位决定是否读取，第二个信号位则决定是否向寄存器写入（保存）新值。另有一个 8 位的输入端子向你提供待写入的数值。
此外，我们还将给你的电路输入两个地址位，分别是 A / B 与 0 / 1。

利用这两个地址位的信号，你可以组合出 4 个不同的地址来，每个地址应该对应一个 8 位寄存器。

[tip]选中元件后按空格键可以进行旋转。[/tip]

$76851096880864* 你能在这有限的空间里塞下 4 个字节的寄存器吗？



=== campaign/ram_component/test.si ===

$29258463778822* 当前输出为空（高阻态），但预期值为 {expected_value}。

$45179662026844* 输出应该为空（高阻态）。

$48251194975794* 当前输出为 {actual_value}，但预期值为 {expected_value}。

$52597500133853* 向地址 {text_add} 写入 {text_value}

$55086379351729* 从地址 {text_add} 读取 {text_state}



=== campaign/ram_component/ui.txt ===

$22107475451139* [left]向地址 ?? 写入 ???[/left]

$27304327624610* [color=#E49F44][b]存储态[/b][/color]

$27457656265551* [color=#E49F44][b]写入 [/b][/color]

$57378010777762* [left]从地址 ?? 读取 ???[/left]

$62207646058430* [color=#E49F44][b]读取 [/b][/color]

$62589960113273* [color=#E49F44][b]地址[/b][/color]

$71008031461945* [color=#E49F44][b]     输入值    [/b][/color]

$85306375920893* [color=#E49F44][b]     地址     [/b][/color]



=== campaign/rng/meta.txt ===

$18488351703350* 你知道像我们这种搭载着确定性代码的机器人是怎样获得创造力和个性的吗？答案就在我们使用的伪随机数生成器上。

$83969937380086* 千变万化

$90664310835282*
这一关里，测例只包含一个输入值，我们把这个值称作随机种子（seed）。我们可以通过以下三个步骤用随机种子来生成一个伪随机数：

[b]32 位异或移位（Xorshift）伪随机数生成算法：[/b]
[box][left]
temp1  = seed  xor (seed  lsr 13)
temp2  = temp1 xor (temp1 lsl 17)
result = temp2 xor (temp2 lsr 5)
[/left][/box]

每次生成伪随机数后，请将结果 result 发送到输出端，然后将其作为新的随机种子生成下一个伪随机数。



=== campaign/rng/test.si ===

$77825640575531* 下一个随机种子应该是 {result}，而非 {output}。



=== campaign/sandbox/meta.txt ===

$58382627590046* 沙盒模式



=== campaign/saving_bytes/hint_solution.txt ===

$73980120059844* 我们只需将“优雅存储”一关的解法拓展为 8 位的版本即可。



=== campaign/saving_bytes/meta.txt ===

$41663630841312* 整存整取

$87293777622656*
搭建一个可以存储一字节数值的电路。

当输入的写入（SAVE）信号位为 [T] 时，将输入的数值存入存储器中。

输出端应始终输出存储器中保存的数值。



=== campaign/saving_bytes/test.si ===

$60269032570207* 预期的输出为 {expected_output}。



=== campaign/saving_gracefully/hint_0.txt ===

$14624167685294* 这一关里你要用到一个延迟线。

$52905927349424* 真值表的输入行则对应关卡的两个输入位和延迟线自身的输出端，因为这个输出端要接回延迟线自身的输入端。

$61760299843073* 让延迟线的输入对应真值表的输出行，

$83682732712729* 你可以建立一个真值表来确定输入延迟线的具体应该是什么数值。

$90057665917240* 只要建立起这个真值表，这一关就不难解开了。

$90652401745526* 所以这个真值表共有 3 行输入，8 种可能的组合。



=== campaign/saving_gracefully/hint_1.txt ===

$16548183735739* 但它只能将数据保留一个周期，所以我们必须将它自身的输出连接到输入上，通过不断刷新来维持其中存储的数值。

$64973475823722* 我们目前唯一具有“存储”功能的组件就是延迟线。



=== campaign/saving_gracefully/hint_2.txt ===

$11101940160071* 当操作引脚处于激活（写入 [T]）状态时，我们希望把输入的值写入延迟线，

$19959785727663* 但是直接将输入引脚接入延迟线会导致短路。



=== campaign/saving_gracefully/hint_solution.txt ===

$10919459809145* 我们可用一个数据选择器来决定要将哪个值写入延迟线中。



=== campaign/saving_gracefully/label.txt ===

$88860903896097* 写入



=== campaign/saving_gracefully/meta.txt ===

$13114757255411*
本关有两个输入。
第一个输入为 [T] 时，你需要用新的数据覆盖已存储的数据。
第二个输入端的数值是需要写入的数据。
输出端需要始终输出当前存储器中保存的数值。

$39874917169400* 优雅存储

$61501859914469*
延迟线允许我们将一个输入值暂存一个时钟周期。不过一个能将输入值保存更长时间的元件会更有用。

我们希望你能搭建这么一个元件。



=== campaign/saving_gracefully/ui.txt ===

$10654649810679* 写入

$63465863198591* 待写入数值



=== campaign/score/hint_0.txt ===

$71529804454649* 你可以搭建一组半加器，利用它们对输入加 1 并输出。



=== campaign/score/hint_1.txt ===

$75346310834154* 这里高电平输入 [T] 是个常量，所以我们可以进一步简化最低位的电路。



=== campaign/score/hint_solution.txt ===

$50044461577278* 最后一路的与门没有用到，我们可以将它也删除。



=== campaign/score/meta.txt ===

$34375498293137* 在这一关里，我们将会引入能效评分系统。你的电路分数取决于运行用时和能耗。

$38383835706006*
在本关里，你需要读取输入值，将其加 1 后输出。

结果中超出 8 位的部分直接舍去即可。

本关的额外要求是你的电路必须只包含至多 40 个基本逻辑门，延迟量不得高于 10。

$40775045205647*
你在之前的关卡中解锁的元件成本取决于对应关卡的得分。

如果你希望降低已有元件的成本，你可以回头优化对应关卡的解法，以减少逻辑门的数量或延迟量。

要想通过这一关，你的异或门必须只包含不多于 3 个基本逻辑门，延迟量也不能超过 2。

$59781832788691*
每个基本逻辑门（与非、或非、与、或）都有 1 单位的响应延迟时间。也就是说，它们会在接收到输入信号的 1 单位时间内完成计算。

一个电路中，从输入到输出端的不同路径有不同的延迟量。整个电路的响应延迟量取决于其中最慢的那条路径，即瓶颈路径（the critical path）。
你可以点击窗口右上角的沙漏图标，来查看瓶颈路径。

$70169388789757*
下面两个算式的值相等，但它们并不等价：

((A + B) + C) + D
(A + B) + (C + D)

它们的结果相同，但后一个式子可以并行计算，因此它可以比第一个算式更早输出结果。

$72877144436007*
此外，每种基本逻辑门在 1 单位时间内还会产生 1 单位能耗。

所以电路在一个时钟周期（时钟刻）内的能耗，等于你所使用的基本逻辑门的总数乘以瓶颈路径的响应延迟量。

$78375324732864*
能够做功的有用能量称作“㶲”。宇宙中的㶲是有限的，如果我们将其全部消耗，宇宙就会陷入热寂。因此，能量的利用效率对宇宙的存续至关重要。

在我们的社会中，低效就是丑陋，而高效等于美妙。

实际上，能耗就是我们用于衡量美丑的客观指标。

$85893273691863* 绝对美感



=== campaign/score/test.si ===

$15039285047182* 输出应为 {expected}。

$46433606967015* 计算 {cycle} + 1



=== campaign/score/ui.txt ===

$85765173996083* 将输入加 1 并输出



=== campaign/second_tick/hint_0.txt ===

$81345258398584* 由真值表可知，只有第一路输入为真（高电平 [T]），

$87387306821265* 第二路输入为假（低电平 [F]）时，电路输出为真（高电平 [T]）。



=== campaign/second_tick/meta.txt ===

$11961528105462* 搭建一个电路，只在第二个时钟周期输出 [T] 。

$69913560783046* 第二周期



=== campaign/signed_negator/hint_0.txt ===

$59964726775903* 你只需要对它按位取反，然后加一。

$77523753173621* 要得到二进制数的相反数，



=== campaign/signed_negator/hint_solution.txt ===

$49596217848125* 请自行探索更好的解法吧！

$55687805352825* 这种解法不是最优雅或者最高效的。



=== campaign/signed_negator/meta.txt ===

$15862778001173*
本关里，输入将被视作有符号整数（最高位为 -128）。请设计电路，从输入端读取数值，并输出其相反数（改变符号）。
例如，4 对应的相反数是 -4，-9 对应的相反数是 9。

$54237470041206* 数值反转



=== campaign/signed_negator/ui.txt ===

$10529708471093* 输入



=== campaign/sort/meta.txt ===

$23043475637417* 本关里，你的任务是从输入端依次读取 16 个数字，将它们从小到大排列后依次输出。

$53593011909329* 美味排行

$79528307974753* 我们正在修订《银河系美食全典》，本次修订的主要工作是加入人类的食物。我们的语言不使用文字，所以全典的页面顺序是按照美味度排列的。



=== campaign/sort/test.si ===

$25018662661467* 排序后的列表中，第 {index} 项应为 {expected}，而非 {output}。



=== campaign/symphony/test.si ===

$17745932940157* 你应该从主存地址 {expected_value} 处读取下一条指令，但当前的取指地址为 {actual_counter}。请检查你在上一周期是否正确更新了程序计数器的值。

$21000091589999* 预期的输出为 {expected_output}，但当前输出为 {output_value}。

$22469925230320* 外存地址 {i} 处的值应为 {expected_value}，而非 {value}。

$29078414770160* 寄存器'zr'（元件'Register File'的零地址处）的值应该始终为 0。

$60841927788704* 你不应该在两条 time_0 指令之间请求访问系统时间。

$70740757119887* 寄存器 {register}（元件'Register File'的地址 {address} 处）的值应为 {expected_value}，而非 {actual_value}。

$74663212299349* 主存地址 {i} 处的值应为 {expected_value}，而非 {value}。

$85916420035294* 输出端应处于激活状态。



=== campaign/symphony_10_stack/meta.txt ===

$29798404581087* 后来居上

$68315222097089*
这一关里，你需要实现一个编程中常用的概念，它叫做“栈”（stack）。和上一关一样，你需要在汇编语言的层面实现相关的操作，而不需要调整你的硬件。一个栈需要支持下面的两个操作：
[left]
  [color=#66ccff]PUSH[/color]（压栈） - 向栈中添加（压入）一个数值
  [color=#66ccff]POP[/color]（弹栈）  - 从栈中取出（弹出）最后加入的数值
[/left]
你可以把一个栈想象成厨房里的一摞盘子。洗盘子的人会把洗好的盘子放在这摞盘子的顶部（压栈，[color=#66ccff]PUSH[/color]），而厨师也会从顶部取走最近洗好的盘子（弹栈，[color=#66ccff]POP[/color]）。

要通过本关，你需要读取一系列输入，根据输入的数值，完成指定的任务：
如果读入的数值非 0，请将这个值压入栈顶，以备之后读取。
如果读入的数值为 0，请将栈顶的数据弹出，并发送到输出设备中。

$90806029597852*
因为栈操作十分常用，我们为你的 Symphony 架构添加了 push 和 pop 两条新指令。它们都是由两条指令构成的的复合操作，并且操作过程中用到了 14 号寄存器 sp。这个寄存器中存放的是栈顶指针（stack pointer），它用于追踪栈顶元素的位置。

push 指令等价于下面两条指令：
[box][left]
sub sp, sp, 4
store_32 [sp], %value
[/left][/box]
pop 指令等价于下面两条指令：
[box][left]
load_32 %destination, [sp]
add sp, sp, 4
[/left][/box]
你可能注意到了，压栈（push）操作会将栈顶指针的值减 4，所以调用栈实际上是从内存的较高地址向较低地址逆向增长的。这么做的目的是为了把内存中较低的地址留出来供你自由支配。



=== campaign/symphony_10_stack/test.si ===

$35910734851012* 栈顶数值应为 {expected_value}，而非 {actual_value}。

$77129086767196* 你没有输出上次弹出栈顶的数值。



=== campaign/symphony_10_stack/ui.txt ===

$35820332981557* 在 Symphony 架构中实现栈操作



=== campaign/symphony_11_functions/meta.txt ===

$28617596738571*
有些时候我们会在程序中反复使用部分代码片段。我们把这些代码称作函数（function）。要想重用某些代码，我们就需要在代码运行过程中，在适当的时候跳转到函数的开头（函数入口）处，并在代码片段结束的位置跳回之前的位置继续运行。我们把跳转到函数入口的操作称作调用（call）函数，从函数跳回原处的操作称作返回（return）。
  
不过要实现函数返回操作，我们需要让同一段函数代码能够返回到多个不同的位置，因此我们需要让函数知道调用点位于代码的什么地方。

要实现这个目标，我们可以在调用函数前，将程序计数器的值保存在寄存器中，并在返回时利用这个值。不过这样做有一个缺点，就是函数无法实现嵌套调用，即一个函数无法调用另一个函数。因为子函数的调用点会将父函数的调用点信息覆盖掉。

试想这样一个场景：我们需要让函数 A 调用函数 B，而函数 B 则要调用函数 C。当函数 C 返回时，我们需要知道函数 B 中调用 C 的位置，而 B 返回时，我们又需要知道 A 中调用 B 的位置。总的来讲，不管函数是以怎样的方式嵌套的，当返回操作发生时，我们需要读取的调用点都是最后一次调用发生的位置。这正是栈所具备的功能。

$41513122622358* 函数调用

$42088257134737* 这一关是一个演示关卡，它主要用于向你展示函数调用是如何完成的，因此本关不包含任何测例。请在进入下一关以前，仔细阅读示例代码，并逐条执行指令，以确保你能充分理解函数调用的方法。这对你完成后续的关卡很有帮助。

$56028205797304* 由于函数一般会改写各个寄存器中的信息，我们可能还需要将寄存器的值一并压入栈中来保存它们的值，这样在函数返回时我们就能将寄存器恢复到调用前的状态。这个操作既可以在调用前完成，也可以在调用后完成，但最好在代码中形成统一的个人风格（调用约定），这样不同代码中的调用方式就能彼此保持一致。

$64240772623662*
这一关里，我们为你的 Symphony 架构添加了调用（call）和返回（ret）指令。它们都是复合操作。

call 指令用于跳转到函数入口。和一般的跳转指令的区别之处在于，在跳转之前，它会将调用点下一行代码的地址（即程序计数器的值加上一个偏移量）压入栈顶。

ret 指令用于从函数中返回到调用点处。它从调用栈顶弹出最后一次调用点地址，并跳转到对应的位置。



=== campaign/symphony_11_functions/new_program.asm ===

$10902022971046* 除 r1 和 r2 外，函数返回时应该保证其它所有寄存器都恢复到调用前的状态

$11016773181609* 最后一次乘法函数调用的结果已存储在 r1 中，直接返回即可

$14412657671278* 将 r3 和 r4 压栈。此后我们可以随意使用它们，直到函数返回时再将保存的值恢复到这两个寄存器中。

$18457350783754* 第一个输入为 2

$21553876748933* 积

$21707356398727* 从关卡输入中读取两个参数

$27088227324511* 乘数

$27592840036827* 第二个输入为 5

$30769341721428* 被乘数

$32724600358227* 恢复函数调用之前 r3 的值

$33479507858734* 计算 2 的 5 次方

$42717933764735* 寄存器 r1 和 r2 用于传递参数，其中 r1 还用于存储返回值

$42740851915963* 剩余的指数

$43461252553161* 函数调用的约定：

$59000482794872* 结果应为 32

$63878589013500* 直到剩余指数为 0 以前，反复将结果乘 2，并将指数减 1

$65068280556611* 恢复函数调用前的寄存器值

$68500361393623* 为寄存器取名可以提高代码可读性

$70634976221207* 将 r3 的值压栈。此后我们可以随意使用 r3 寄存器，直到函数返回时再将保存的值恢复到 r3 中



=== campaign/symphony_11_functions/ui.txt ===

$51514522389782* 逐行运行程序，观察函数调用如何进行



=== campaign/symphony_12_budget/meta.txt ===

$68182570848466* 本关的任务非常直白（但不一定简单），你需要调整 Symphony 架构，将每个时钟刻（时钟周期）的延迟量降低到至多 175。你很可能需要回头对之前的关卡中解锁的各种元件进行大幅度的优化。

$69806637130600* 快速乐章



=== campaign/symphony_12_budget/ui.txt ===

$17052191264122* 优化 Symphony 架构以将总延迟量降低到阈值以内



=== campaign/symphony_1_nand/meta.txt ===

$36086882016175*

Symphony 架构中，多数指令都带有两个参数，并输出一个结果（如 ADD、OR 等）。

为了实现这个功能，[color=#e49f44]Symphony[/color] 的每条指令占用 4 个字节，这样你就可以在一条指令中编码所有三个操作数。比如说，我们可以将任意两个寄存器的值相加，并将结果存入任意一个寄存器中，而这三个寄存器的地址都在指令的参数中指定。另外，所有的程序指令都存储在一个名为“Main Memory”（主存）的 RAM 组件中。

$62556352127349* 千头万绪

$70083014183793* 终于到了该搭建 [color=#e49f44]Symphony[/color] 架构的时候了！

$83483553172261*
现在，请你在这一关里，按照我们上述的解释和要求，利用给定的硬件，搭建一个能访问指定寄存器，并执行 NAND 指令的电路。它是 Symphony 架构的基础。

以下是不使用立即数时 Symphony 架构中指令的编码方式：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#bbbbbb]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

参数 A、参数 B 和目标都是寄存器地址，你需要使用“条分缕析”关卡中解锁的指令译码器从指令中取出这三个地址。注意：内存组件的加载和存储端口接收的地址是以字节为单位的，但每个 32 位的寄存器占用 4 个字节。这意味着你需要计算寄存器的地址，而不是直接把寄存器的编号传递给内存读写端口。

另外，在这一关中，[color=#ff9800]Mode[/color]（运行模式）始终为 1，而[color=#ff6680]Opcode[/color]（操作码）始终为 0。这意味着我们只需要从指定的寄存器中读出第一个参数与第二个参数，进行 NAND 运算，并将结果存入目标寄存器中。目前你可以直接使用一个 32 位与非门来代替 ALU。

[center][image="cn_symphony_diagram_1.png"][/center]

$88649654188267*
以下是 [color=#e49f44]Symphony[/color] 的 16 个寄存器的名称：

[left]
                0 zr
                1 r1
                2 r2
                3 r3
                4 r4
                5 r5
                6 r6
                7 r7
                8 r8
                9 r9
                10 r10
                11 r11
                12 r12
                13 r13
                14 sp
                15 flags
[/left]

零号寄存器“zr”的值永远是 0，或者说写入“zr”的任何数值都会被丢弃，我们可以利用这一特点来简化一些指令的硬件实现。“sp”和“flags”本质上是两个普通的寄存器，它们有特别的名称，并将在后续关卡中被留作特殊用途。你应该尽量避免手动擦写其中的数值，除非你明白这样做会产生什么结果。

和 Overture 架构不同，这一次我们不使用单独的 16 个寄存器。我们使用一个名为“Register File”的内存组件来模拟这一组寄存器。



=== campaign/symphony_1_nand/test.si ===

$34545926188340* 你应该从主存地址 {expected_value} 处读取下一条指令，但当前的取指地址为 {actual_counter}。请检查你在上一周期是否正确更新了程序计数器的值。

$35453700742253* 你不应该在两条 time_0 指令之间请求访问系统时间。

$40674051088628* 屏幕组件的 3 号设定的值应为 {expected_value}，而非 {value}。

$55420494010123* 主存地址 {i} 处的值应为 {expected_value}，而非 {value}。

$56149980430079* 输出端应处于激活状态。

$68153781027719* 外存地址 {i} 处的值应为 {expected_value}，而非 {value}。

$74043498193765* 输出应为 {expected_output}，而非 {output_value}。

$81124009043205* 寄存器'zr'（元件'Register File'的零地址处）的值应该始终为 0。

$84654787309709* 寄存器 {register}（元件'Register File'的地址 {address} 处）的值应为 {expected_value}，而非 {actual_value}。



=== campaign/symphony_1_nand/ui.txt ===

$21345632528660* 为 Symphony 架构搭建基础，实现读取指令和读写寄存器的功能



=== campaign/symphony_2_io/hint_solution.txt ===

$34652721020070* 图中灰色线路所示即为添加读写交互功能所需的电路。



=== campaign/symphony_2_io/meta.txt ===

$66929200224494*
这一关里，我们要向 [color=#e49f44]Symphony[/color] 架构添加能够读取输入和保存输出的设备。

指令的位模式重述如下：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#bbbbbb]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

和 [color=#e49f44]Overture[/color] 架构类似，Symphony 架构也有四种运行模式：

0 IO（外设模式）
1 ALU（运算模式）
2 JUMP（跳转模式）
3 RAM（访存模式）

这一关里，你暂时只需要关心前两个模式（IO/ALU）。处于 ALU（运算）模式时，和上一关一样，你只需要执行 NAND 操作即可。处于 IO（外设）模式时，你需要根据操作码（OpCode），让你的电脑采取下面三种操作之一：

0 nop  无操作
1 in   将输入设备的值发送到[color=#ffe666]目标寄存器[/color]
2 out  将参数 B（[color=#66ccff]argument B[/color]）的值发送到输出设备

$85119202720349* 读写交互



=== campaign/symphony_2_io/ui.txt ===

$76620689360899* 向 Symphony 架构添加输入输出设备



=== campaign/symphony_3_alu/hint_solution.txt ===

$23277299590423* 用之前搭建的 ALU 代替按位与非元件即可完成任务。

$90347458725803* 图中橙色线路所示即为向 ALU 发送操作码所需的电路。



=== campaign/symphony_3_alu/meta.txt ===

$13069282666558*
这一关里，你需要将“更新换代”一关里搭建的 ALU 整合进 Symphony 架构中。ALU 需要执行的操作由指令中的 [color=#ff6680]Opcode[/color]（操作码）部分给出。

指令的位模式重述如下：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#bbbbbb]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

$78613176066303* 引擎发动



=== campaign/symphony_3_alu/ui.txt ===

$54189071002426* 向 Symphony 架构添加 ALU



=== campaign/symphony_4_immediates/hint_solution.txt ===

$61996387838431* 图中紫色线路所示即为添加立即数功能所需的电路。



=== campaign/symphony_4_immediates/meta.txt ===

$46968415562883* 原装直达

$74993560224545*
你可以参考下面的图解来对你的电脑进行升级。

[image="cn_symphony_diagram_2.png"]


$85471608475185*
有些时候，从代码中直接读取数字比从寄存器中读取数值更方便。直接编码在代码中的字面值参数称作立即数（immediate value）。在 [color=#e49f44]Symphony[/color] 架构中，我们需要进行适当的硬件配置，从而允许我们用立即数代替寄存器地址作为指令的第二个输入参数（参数 B）。当我们使用立即数作为参数 B 时，指令中的左起第四位会被置为 1，此时指令的后两个字节就是立即数的值：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
              [color=#9966ff]0[/color]/[color=#9966ff]1[/color] = Immediate mode（立即数指示位）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B，可以是立即数）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

当参数 B 不是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

当参数 B 是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]1[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#66ccff]BBBBBBBB BBBBBBBB[/color]



=== campaign/symphony_4_immediates/ui.txt ===

$90023711394112* 向 Symphony 架构添加立即数（immediate）功能



=== campaign/symphony_5_jumps/meta.txt ===

$39122914366346* 指令折跃

$57225943470132*
下面是 [color=#e49f44]Symphony[/color] 的工作模式（[color=#ff9800]Modes[/color]）：

0 IO（外设模式）
1 ALU（运算模式）
2 JUMP（跳转模式）
3 RAM（访存模式）

在这一关中，我们要实现 JUMP（条件跳转）模式。一如既往，指令的位模式如下所示：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
              [color=#9966ff]0[/color]/[color=#9966ff]1[/color] = Immediate mode（立即数指示位）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B，可以是立即数）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

当参数 B 不是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

当参数 B 是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]1[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#66ccff]BBBBBBBB BBBBBBBB[/color]

在 JUMP 模式下，[color=#66ff99]参数 A[/color] 指定的寄存器中存放的是标志位（flags），这个值需要与指令中给出的条件（即操作码 [color=#ff6680]Opcode[/color]）进行比较。你可以直接用“归并判定”这一关里搭建的自定义元件“cond”完成这个比较操作。

如果标志位和指令中的条件匹配成功，那么你要用 [color=#66ccff]参数 B[/color] 覆盖计数器的值。



=== campaign/symphony_5_jumps/ui.txt ===

$88550064597726* 为 Symphony 架构添加条件跳转功能



=== campaign/symphony_6_ram/hint_solution.txt ===

$78759770178685* 图中新添加的紫色与粉色线路即为实现访存模式所需的电路。



=== campaign/symphony_6_ram/meta.txt ===

$41276257356528* 内存

$43585926436336* 注意，内存的读写端口是从上到下依次执行操作的。如果一个读取端口位于写入端口的下方，它会在写入之后才读取；如果位于写入端口上方，则会在写入之前读取。当端口读写同一地址时，这个顺序会很重要，因为所有读取端口都会尝试等待它们上方的写入端口完成操作，也就是会对这些写入端口产生依赖关系。在这一关中，所有的读取端口都必须位于写入端口的上方，否则就会导致循环依赖。

$65386575947998*
在这一关里，我们要实现 RAM（访存）模式。目前，该模式有六个操作码（[color=#ff6680]Opcode[/color]）：
[left]
                [color=#ff6680]0[/color] load_8
                [color=#ff6680]1[/color] load_16
                [color=#ff6680]2[/color] load_32
                [color=#ff6680]3[/color] [color=#bbbbbb]（留作它用）[/color]
                [color=#ff6680]4[/color] store_8
                [color=#ff6680]5[/color] store_16
                [color=#ff6680]6[/color] store_32
[/left]
读取类指令（load_XX）应从指令的 [color=#66ccff]参数 B[/color] 对应的内存地址处读出数值，并将结果存入 [color=#ffe666]目标[/color] 寄存器。

写入类指令（store_XX）应将 [color=#66ff99]参数 A[/color] 寄存器中的数值，存入主存位于 [color=#66ccff]参数 B[/color] 的地址处。

所有指令读写的内存地址偏移量都以字节为单位。数字后缀决定了从内存读取或写入的位宽。例如，load_8 指令应读出 8 位数据，store_16 指令应从目标地址开始写入 16 位数据。

$69462908463194*
在这一关里，我们要添加对主存（即程序所在的内存单元 Main Memory）的读取和写入功能。我们希望能够实现对于 32 位、16 位和 8 位三种字长的数据读写操作，因此需要为主存元件额外添加 3 个读取端口和 3 个写入端口。

请将我们新提供的端口元件插入到指令读取端口与主存之间。

$73426457129430*
和先前的关卡一样，[color=#e49f44]Symphony[/color] 的工作模式（[color=#ff9800]Mode[/color]）如下：

[left]
                [color=#ff9800]0[/color] IO（外设模式）
                [color=#ff9800]1[/color] ALU（运算模式）
                [color=#ff9800]2[/color] JUMP（跳转模式）
                [color=#ff9800]3[/color] RAM（访存模式）
[/left]

指令的位模式如下：
[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
              [color=#9966ff]0[/color]/[color=#9966ff]1[/color] = Immediate mode（立即数指示位）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B，可以是立即数）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

当参数 B 不是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

当参数 B 是立即数时，指令的位模式为：
[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]1[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#66ccff]BBBBBBBB BBBBBBBB[/color]



=== campaign/symphony_6_ram/ui.txt ===

$51703376131802* 在 Symphony 架构中实现内存的读取/写入（load/store）指令



=== campaign/symphony_7_ssd/hint_solution.txt ===

$28652182390799* 图中新添加的紫色与粉色线路即为操作外存所需的电路。



=== campaign/symphony_7_ssd/meta.txt ===

$23620554597332*
这一关里我们要为计算机添加一个非易失性的大容量存储器（外存），让它能在每次重启后仍然保留此前已有的数据。

你需要为这个存储单元添加两条对应的指令 pload 和 pstore。它们和前一关里 32 位字长的访存指令功能类似，唯一的区别是，这两条指令控制的是新的外存单元。

下表列出了我们在访存模式下所需使用的全部操作码（[color=#ff6680]Opcode[/color]）：
[left]
                [color=#ff6680]0[/color] load_8
                [color=#ff6680]1[/color] load_16
                [color=#ff6680]2[/color] load_32
                [color=#ff6680]3[/color] pload
                [color=#ff6680]4[/color] store_8
                [color=#ff6680]5[/color] store_16
                [color=#ff6680]6[/color] store_32
                [color=#ff6680]7[/color] pstore
[/left]

$76705374584193* 记忆永存



=== campaign/symphony_7_ssd/ui.txt ===

$89678353617146* 向 Symphony 架构添加非易失性存储器



=== campaign/symphony_8_io_devices/default.isa ===

$28545157055801* 将寄存器 %a 的值压入栈顶。该指令等价于下列指令序列：   sub sp, sp, 4   store_32 [sp], %a

$34859363394334* 将立即数 %b 存入寄存器 %a。

$40508048121543* 对立即数 %b 按位取反，将结果存入寄存器 %a。

$48332460366102* 返回上次的函数调用点。该指令会重写 flag 寄存器。该指令等价于下列指令序列：   load_32 flags, [sp]   add sp, sp, 4   jmp flags

$53941960758392* 将寄存器 %b 的值写入寄存器 %a。

$54469754973269* 将栈顶值弹出并存入寄存器 %a。该指令等价于下列指令序列：   load_32 %a, [sp]   add sp, sp, 4

$55357258069734* 对寄存器 %b 的值按位取反，将结果存入寄存器 %a。

$57504570243305* 对立即数 %b 求相反数，将结果存入寄存器 %a。

$57788320241950* 调用函数 %a。该指令会重写 flag 寄存器。该指令等价于下列指令序列：   counter flags   add flags, flags, 20   sub sp, sp, 4   store_32 [sp], flags   jmp %a

$72894099288447* 对寄存器 %b 的值求相反数，将结果存入寄存器 %a。



=== campaign/symphony_8_io_devices/hint_solution.txt ===

$48843089545173* 图中新添加的灰色线路即为操作新的外设所需的电路。



=== campaign/symphony_8_io_devices/meta.txt ===

$67457044658869*
本关里，你需要向 Symphony 架构添加三个新的外设：显示屏、实时时钟和键盘。

你还需要将显示屏链接到主存元件上。



=== campaign/symphony_8_io_devices/new_program.asm ===

$10169473219025* 1 秒 = 1_000_000_000 纳秒 = 0x0000_0000_3B9A_CA00

$11549850182703* y 坐标

$16841324702501* 机器人

$22405816552972* 方向

$23344524651761* 更新 next_cycle

$25470599373421* 在新位置重绘敌人

$25474902303790* 步进方向

$26430777268618* 机器人下移

$28230914387367* 金币

$29369794309677* TODO: 将空单元格和有金币单元格分开处理

$31647601023268* 精灵贴图跳转地址表

$33327526977497* 敌人

$33450896282702* 占位符

$34042928458359* 模 3

$35647670060017* 空

$36791496238134* 2 * 指令字长 = 8

$37230877526029* 敌人右移

$37647180126584* 在新位置重绘机器人

$38695844571056* 低 32 位和上溢

$40959483784712* 机器人右移

$45301848117435* 敌人下移

$50069163371185* 敌人左移

$50501450979711* 机器人上移

$55263046326109* 撞墙 -> 取消移动

$55673115734516* 以 4 字节为单位补齐

$61792431057747* x 坐标

$62236058044269* [补齐 4 字节]

$64851396075477* 2 * 指令字长 = 8

$67744627518982* 金币

$69893421560125* 机器人左移

$72366220861688* 敌人上移

$73803385159414* 起始值为 0

$75937352730902* 0.5 秒 = 500_000_000 纳秒 = 0x0000_0000_1DCD_6500



=== campaign/symphony_8_io_devices/test.si ===

$18975134592059* 输出端应处于激活状态。

$26871980917450* 外存地址 {i} 处的值应为 {address}，而非 {value}。

$29202969341865* 系统时间不正确（请确保在两条 time_0 指令间正确缓存了上一次读取的时间戳）。

$29909286517152* 寄存器'zr'（元件'Register File'的零地址处）的值应该始终为 0。

$30816527015736* 输出应为 {expected_output}，而非 {output_value}。

$31400969059429* 寄存器 {register}（元件'Register File'的地址 {address} 处）的值应为 {expected_value}，而非 {actual_value}。

$41024505081324* 你应该从主存地址 {counter_value} 处读取下一条指令，但当前的取指地址为 {actual_counter}。请检查你在上一周期是否正确更新了程序计数器的值。

$42960087865089* 屏幕组件的 {i} 号设定的值应为 {expected_value}，而非 {value}。

$46474751521062* 你需要将屏幕组件链接到主存“Main Memory”上。点击屏幕组件左上角的红色按钮以选择链接目标。

$78917660933958* 主存地址 {i} 处的值应为 {address}，而非 {value}。



=== campaign/symphony_8_io_devices/ui.txt ===

$63394282539727* 向 Symphony 架构添加额外的输入/输出设备



=== campaign/symphony_9_aliases/default.isa ===

$11626177279992* 若 flags 寄存器中的结果满足 a 大于 b（无符号），则令程序跳转至地址 %a。

$12835125621741* 将立即数 %b 写入显示屏的选项寄存器 %a。

$13110303123442* 以寄存器 %adr 的值为地址，将寄存器 %value 的值写入外存。

$13576771671264* 将寄存器 %c 的值作为位移量，对寄存器 %b 的值执行逻辑左移，并将结果存入寄存器 %a。

$15915531259935* 将立即数 %a 发送到标准输出设备。

$16685334571248* 将固定值 %c 作为位移量，对寄存器 %b 的值执行逻辑右移，并将结果存入寄存器 %a。

$18254089726214* 将寄存器 %a 的值发送到标准输出设备。

$19953421010778* 将寄存器 %value 的低 8 位值写入主内存的地址 %adr 处。

$23349431010010* 将寄存器 %b 的值和固定值 %c 相加，并将结果存入寄存器 %a。

$23396316982953* 从主内存的地址 %adr 处读取 8 位数值，并存入寄存器 %dest。

$26183125927881* 若 flags 寄存器中的结果满足 a 小于等于 b（无符号），则令程序跳转至地址 %a。

$27219499692147* 以寄存器 %adr 的值为地址，从主内存中读取 16 位数值，并存入寄存器 %dest。

$27868418224252* 读取一个键盘输入值并将其存入寄存器 %a。

$28652904157569* 将寄存器 %b 和寄存器 %c 的值相减，并将结果存入寄存器 %a。

$29562677483890* 将寄存器 %value 的低 16 位值写入主内存的地址 %adr 处。

$30574433901064* 对寄存器 %b 的值和固定值 %c 执行按位或运算，并将结果存入寄存器 %a。

$31763492459833* 若 flags 寄存器中的结果满足 a 小于 b（无符号），则令程序跳转至地址 %a。

$37102964808364* 将寄存器 %a 的值和固定值 %b 进行比较，并将结果存入'flags'寄存器。

$37333076617857* 对寄存器 %b 和寄存器 %c 的值执行按位或非运算，并将结果存入寄存器 %a。

$39857449355186* 将寄存器 %b 的值写入显示屏的选项寄存器 %a。

$40732211165530* 对寄存器 %b 和寄存器 %c 的值执行按位或运算，并将结果存入寄存器 %a。

$42626144645228* 将寄存器 %c 的值作为位移量，对寄存器 %b 的值执行算术右移，并将结果存入寄存器 %a。

$44524771082050* 从标准输入设备读入一个值，并将其存入寄存器 %a。

$46087142860391* 对寄存器 %b 的值和固定值 %c 执行按位或非运算，并将结果存入寄存器 %a。

$46967848572964* 对寄存器 %b 和寄存器 %c 的值执行按位异或运算，并将结果存入寄存器 %a。

$47442552951774* 以寄存器 %adr 的值为地址，将寄存器 %value 的低 16 位值写入主内存。

$51030225266712* 将寄存器 %b 和寄存器 %c 的值相加，并将结果存入寄存器 %a。

$53499765587663* 若 flags 寄存器中的结果满足 a 大于等于 b（有符号），则令程序跳转至地址 %a。

$54565380946620* 将寄存器 %a 和 %b 中的值进行比较，并将结果存入'flags'寄存器。

$54577249258785* 将固定值 %c 作为位移量，对寄存器 %b 的值执行逻辑左移，并将结果存入寄存器 %a。

$55551510150818* 将固定值 %c 作为位移量，对寄存器 %b 的值执行算术右移，并将结果存入寄存器 %a。

$57200935026773* 以寄存器 %adr 的值为地址，从主内存中读取 8 位数值，并存入寄存器 %dest。

$59344052643304* 将寄存器 %value 的值写入外存的地址 %adr 处。

$61040780958703* 以寄存器 %adr 的值为地址，将寄存器 %value 的低 8 位值写入主内存。

$66785854415645* 对寄存器 %b 的值和固定值 %c 执行按位异或运算，并将结果存入寄存器 %a。

$67019902294705* 将寄存器 %c 的值作为位移量，对寄存器 %b 的值执行逻辑右移，并将结果存入寄存器 %a。

$67178948469318* 若 flags 寄存器中的结果满足 a 不等于 b，则令程序跳转至地址 %a。

$67376584796076* 将程序计数器的值写入寄存器 %a。

$67495552371225* 将寄存器 %b 的值和固定值 %c 相减，并将结果存入寄存器 %a。

$68219187873304* 将系统时间的高 32 位数值写入寄存器 %a。

$69550893885320* 以寄存器 %adr 的值为地址，将寄存器 %value 的值写入主内存。

$69632418904622* 以寄存器 %adr 的值为地址，从主内存中读取 32 位数值，并存入寄存器 %dest。

$71317192057126* 若 flags 寄存器中的结果满足 a 大于 b（有符号），则令程序跳转至地址 %a。

$71637103729391* 若 flags 寄存器中的结果满足 a 小于 b（有符号），则令程序跳转至地址 %a。

$72280171778920* 从外存的地址 %adr 处读取 32 位数值，并存入寄存器 %dest。

$72551400437977* 将系统时间的低 32 位数值写入寄存器 %a。

$73559051740347* 将寄存器 %value 的值写入主内存的地址 %adr 处。

$74148826866592* 令程序跳转至寄存器 %a 指定的地址。

$75302656449127* 对寄存器 %b 的值和固定值 %c 执行按位与非运算，并将结果存入寄存器 %a。

$77040234358389* 若 flags 寄存器中的结果满足 a 小于等于 b（有符号），则令程序跳转至地址 %a。

$77232719678109* 从主内存的地址 %adr 处读取 16 位数值，并存入寄存器 %dest。

$82087388048746* 若 flags 寄存器中的结果满足 a 大于等于 b（无符号），则令程序跳转至地址 %a。

$85679146831122* 对寄存器 %b 和寄存器 %c 的值执行按位与运算，并将结果存入寄存器 %a。

$85822609095465* 从主内存的地址 %adr 处读取 32 位数值，并存入寄存器 %dest。

$86705346481666* 对寄存器 %b 和寄存器 %c 的值执行按位与非运算，并将结果存入寄存器 %a。

$86713121915282* 对寄存器 %b 的值和固定值 %c 执行按位与运算，并将结果存入寄存器 %a。

$88180305667389* 若 flags 寄存器中的结果满足 a 等于 b，则令程序跳转至地址 %a。

$88272577071256* 不执行任何操作。

$89257021109854* 以寄存器 %adr 的值为地址，从外存中读取 32 位数值，并存入寄存器 %dest。

$90876214388280* 令程序跳转至地址 %a。



=== campaign/symphony_9_aliases/label.txt ===

$18099138932731* 非易失性存储器 - Persistent Memory

$28246040923235* 寄存器堆 - Register File

$35059654572638* 系统时间

$41903613959902* 主存 - Main Memory

$79162322081640* 键盘

$80985404567327* 屏幕



=== campaign/symphony_9_aliases/meta.txt ===

$20456965663323* 如此包装

$41535895646297*
和之前的关卡一样，这一关里，我们会引入一些新的指令，而你需要实现这些指令对应的操作。不一样的地方在于，这一关里，你不需要调整你的硬件和电路布局。你需要通过修改汇编指令集架构（instruction set architecture，缩写为 ISA），利用已有的硬件功能来实现新的指令。

请打开汇编代码编辑器，点击窗口左上方的“spec.isa”标签页，切换到指令集视图。你需要先阅读已有指令的定义，了解每条指令是如何实现的，然后向指令集中添加下面三条指令：

[b]mov[/b]
"[b]mov[/b]" 代表移动指令（move）。该指令应接收两个操作数，功能是将第二个操作数的值存入第一个操作数指定的寄存器中。

[b]neg[/b]
"[b]neg[/b] 代表求相反数（negate）。该指令应接收两个操作数，功能是计算第二个操作数的相反数，并将结果存入第一个操作数指定的寄存器中。

[b]not[/b]
"[b]not[/b]" 代表按位逻辑非。该指令应接收两个操作数，功能是对第二个操作数执行按位取反（非运算），并将结果存入第一个操作数指定的寄存器中。


定义好这三条指令后，你就可以运行汇编代码来通过这个关卡了。



=== campaign/symphony_9_aliases/new_program.asm ===

$71972143734450* 十六进制字面值



=== campaign/symphony_9_aliases/test.si ===

$44683006232656* 第一条指令应该将数值 0x1235 写入寄存器 r1 中。

$67087756287234* 寄存器 r3 的值应为 0x1234。

$83123414679662* 寄存器 r2 的值应为 0xffffedcb。



=== campaign/symphony_9_aliases/ui.txt ===

$13320201556243* 向指令集中添加新指令的定义



=== campaign/symphony_alu/meta.txt ===

$52048822283735*
我们给你 Overture 架构的 ALU 制作了一个副本。现在是时候将它也升级到 32 位，并为其添加一些新的计算功能了。

需要实现的操作码列表：

[color=#87a8c8]0 NAND（按位与非）
1 OR（按位或）
2 AND（按位与）
3 NOR（按位或非）
4 ADD（加法）
5 SUB（减法）
6 XOR（按位异或）
7 LSL（逻辑左移）
8 LSR（逻辑右移）
9 ASR（算术右移）
10 CMP（比较大小）[/color]

其中计算比较标志的元件 cmp 正是你在“举一反三”这一关中搭建好的那个版本。

$71902120982324* 更新换代



=== campaign/symphony_alu/ui.txt ===

$69427874681706* 搭建用于 Symphony 架构的算术逻辑单元（ALU）



=== campaign/symphony_cmp/meta.txt ===

$37729390402296* 举一反三

$64818361855764*
在这一关里，你需要以三种不同方式比较两路 32 位输入的大小。每个结果都是一个 1 位的值，称为“标志位”（flag）。

输出包含 3 个标志位，它们的含义如下：
如果两路输入相等，则将最低位（bit 0）设为 1。
如果在无符号模式下，第一路输入小于第二路输入，则将次低位（bit 1）设为 1。
如果在有符号模式下，第一路输入小于第二路输入，则将第三位（bit 2）设为 1。

如需学习如何制作 32 位元件，请参见“大步流星”关卡。



=== campaign/symphony_cmp/test.si ===

$55730459238598* 预期输出应为 {a}{b}{c}。



=== campaign/symphony_cmp/ui.txt ===

$73310930628112* 搭建 Symphony 架构使用的比较标志（flag）生成器



=== campaign/symphony_condition_test/label.txt ===

$13327132168076* 输出

$17010689474441* 目标条件

$25959617344671* 标志



=== campaign/symphony_condition_test/meta.txt ===

$20911185106374*
本关带有两个输入端子。第一个输入值是之前关卡中生成的比较标志（flags），包含 3 个二进制位。第二个输入值是一个 4 位的目标条件值（condition）。我们需要判断给定的比较标志是否满足目标条件值。更具体地讲，你需要将两路输入的最低 3 位逐对比较。只要有一对数位同时为 [T]，条件就视作成功匹配，此时你需要输出 [T]。

另外，第二个输入的第 4 位是一个反转指示位。当这一位为 [T] 时，你需要将输出的结果反转。也就是说，如果这一位为 [T]，并且条件匹配成功，那么你就应该输出 [F]。

$90224867995967* 归并判定



=== campaign/symphony_condition_test/test.si ===

$33181499064044* 输出不应为空（高阻态）

$73051402798264* 正确的输出值应为 {U1 result}。



=== campaign/symphony_counter_1/label.txt ===

$41164574218692* 计数值

$42019997838216* 步进/覆写

$48990052180226* 待写入数值



=== campaign/symphony_counter_1/meta.txt ===

$56387381898532* 大步流星

$76860406179468*
要改变一个元件的位宽，你需要使用左侧菜单中的“设置位宽”工具（其图标是一个双向箭头，下面有一个数字）。

右键单击这个按钮即可调整要设置的位宽值。
选中这个工具后，左键单击电路中的元件，即可为元件设定对应的位宽。
除此以外，你在电路中新添加的所有整型元件的默认位宽都是这个工具当前使用的位宽。

$77897142643435*
本关里，你需要搭建一个 32 位的计数器，其中存储的值每个时钟刻增加 4。和以前一样，你需要为计数器配备一个写入功能，可以按需擦写其中的数值。

此外，你还需要将电路自带的存储器探针链接到电路中的一个 32 位的寄存器上。



=== campaign/symphony_counter_1/test.si ===

$54301125260332* 存储的数值应为 {expected_memory}，而非 {memory_value}。

$70376380014778* 输出不应为空（高阻态）

$84451713761977* 输出应为 {expected_memory}



=== campaign/symphony_counter_1/ui.txt ===

$81792554779622* 搭建一个位宽为 32、每周期步进量为 4 的计数器。



=== campaign/symphony_decoder/label.txt ===

$16402377924132* 使用立即数

$24747841106265* 参数 B

$26207217884026* 操作码

$26325060783055* 参数 A

$40584554497383* 立即数值

$48212238534381* 指令

$48506758479060* 运行模式

$67128656777473* 目标



=== campaign/symphony_decoder/meta.txt ===

$13883461694525* 条分缕析

$41138026161536*
你需要使用静态索引器元件来完成本关。

静态索引器是一种特殊元件，它可以在不引入任何延迟和门开销的前提下，从一根导线中取出特定的若干位数值。点击元件后，在下方面板中可以调整元件截取数据的偏移量（正数表示右移），点击元件左侧的数字窗口则可以设置输出位宽。

$71911284169222*

搭建一个电路，将 Symphony 的指令拆分为不同的部分。这个元件在后面的关卡里会很有用。

Symphony 指令有两种编码格式，取决于指令中是否使用了立即数：

[left]
                [color=#ff9800]M[/color] = Mode（运行模式）
                [color=#ff6680]O[/color] = Opcode（操作码）
              [color=#9966ff]0[/color]/[color=#9966ff]1[/color] = Immediate bit（立即数指示位）
                [color=#ffe666]D[/color] = Destination register（目标寄存器）
                [color=#66ff99]A[/color] = Argument A（参数 A）
                [color=#66ccff]B[/color] = Argument B（参数 B，可以是立即数）
                [color=#bbbbbb]0[/color] = Unused / zero（未使用或为零）
[/left]

不使用立即数时，参数 B 和参数 A 都是 4 位的地址：

[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]0[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#bbbbbb]0000[/color][color=#66ccff]BBBB[/color] [color=#bbbbbb]00000000[/color]

使用立即数时，参数 B 变为一个 16 位的字面值：

[color=#bbbbbb]0[/color][color=#ff9800]MM[/color][color=#9966ff]1[/color][color=#ff6680]OOOO[/color] [color=#ffe666]DDDD[/color][color=#66ff99]AAAA[/color] [color=#66ccff]BBBBBBBB BBBBBBBB[/color]
  



=== campaign/symphony_decoder/test.si ===

$15174125339458* 操作码（Opcode）应为 {opcode}，而非 {actual_opcode}。

$31544476297744* 目标应为 {dest}。

$31942264008156* 参数 B 应为 {b}。

$45701446129480* 立即数的值应为 {immediate_value}。

$63089562267538* 立即数指示位应为 {immediate}。

$64926808682290* 运行模式（Mode）应为 {mode}。

$82638458430252* 参数 A 应为 {a}。



=== campaign/symphony_decoder/ui.txt ===

$51036929729507* 搭建 Symphony 架构的指令译码器



=== campaign/the_bus/hint_0.txt ===

$42863588667057* 利用开关将多路输出连接到同一条线路上。



=== campaign/the_bus/hint_1.txt ===

$88955803760495* 选取输入则和数据选择器的思路相同。



=== campaign/the_bus/hint_solution.txt ===

$55189990966587* 用和数据选择器类似的构造，通过控制开关来实现共用输入端，

$86286155471986* 中间共用的紫色线路即为总线。



=== campaign/the_bus/label.txt ===

$25477689162292* 输出选通位

$25535487507842* A

$43340511034957* 输入选通位

$43474590938240* Y

$47236089523392* X

$65041743851294* B



=== campaign/the_bus/meta.txt ===

$10949534274977* 总线

$25369396405852*
本关有 2 个 8 位输入端和 2 个 8 位输出端。你的目标是将数值从指定的输入端复制到指定的输出端。
  
此外另有两个 1 位的输入，第一个指定你应该从哪个输入端获取数值，而第二个指定你应该将数值复制到哪个输出端。

每个时钟周期里，应该只有一路输出取得目标数值。另一路输出引脚和输入断开（处于高阻态）。后者用“-”表示。



=== campaign/the_bus/test.si ===

$28173496384607* 输出 Y 的值应为 {val}。

$46672500255781* 输出 X 应为空（高阻态）。

$65293894030728* 输出 X 的值应为 {val}。

$69214136994673* 将 {source} 的值发送到 {destination}。

$75577618213381* 输出 Y 应为空（高阻态）。



=== campaign/the_bus/ui.txt ===

$31341803878224* 搭建电路，实现将指定输入端的数值发送到指定输出端的功能。



=== campaign/tower/meta.txt ===

$23374750315066* 汉诺塔是一个著名的数学问题。在这个问题中，桌上插有三根金属钎，其中一根串有一叠金属片，盘片自下而上由大到小排列。你的目标是将这些盘片移动到另一根指定的金属钎上。这个问题的难点在于，你一次只能移动一摞盘片中最顶上的那一个，并且所有金属钎上的盘片都必须保持下大上小的堆叠次序。

$29450953142176* 汉诺塔

$62636370223849*
了不起！地球人，你已经通过了我们所有的测试！没想到从最简单的与非门出发，你居然能走得这么远。

必须承认，人类完全有资格在星系联邦中占据一席之地。

$72724057674158*
本关中，每个测例包含 4 个输入，它们的含义依次如下所列：
disk_nr - 盘片的最大号码（2 至 4；号码从 0 开始）
source - 初始串有盘片的金属钎号码（源）
destination - 盘片移动的目标金属钎号码（目标）
spare - 第三根金属钎（除源和目标以外）的号码

你可以向输出端发送下列数值来控制一块电磁铁，从而移动金属盘片：
[left]
                0 - 将电磁铁移动到 0 号金属钎
                1 - 将电磁铁移动到 1 号金属钎
                2 - 将电磁铁移动到 2 号金属钎
                5 - 切换电磁铁的开关状态
[/left]

你可以先尝试用方向键和回车键控制电磁铁，进行试玩。

$81427576809439*
这一关有一定难度，但也是一个练习函数调用的好问题。下面给出的是一个参考算法，它需要借助递归函数（recursive function）来实现。“递归”的意思是函数自己调用自己。

[b]汉诺塔算法（伪代码）：[/b]
[box][left]func move(disk_nr, source, dest, spare) {
    if disk_nr is 0 {
        move disk from source to dest
    } else {
        move(disk_nr - 1, source, spare, dest)
        move disk from source to dest
        move(disk_nr - 1, spare, dest, source)
    }
}[/left][/box]

[tip]注意在调用函数时将可能改写的寄存器压栈以将其保护起来，并在返回时弹出。[/tip]



=== campaign/tower/ui.txt ===

$39419617008574* 错了！你把大盘片放在小盘片的上面了！



=== campaign/xnor/hint_0.txt ===

$89305883777750* 发现了吗？同或门（XNOR）的输出和异或门（XOR）正好相反。



=== campaign/xnor/meta.txt ===

$29396170535219* 搭建一个和异或门输出相反的电路，即同或门（XNOR）。

$50956872142719* 同或门（XNOR）

$85674599929809* 上次我们来到地球的时候，这里的大多数生物还是巨型爬行动物。那都是些既没智商也没情商的家伙，根本不适合加入我们高贵的星系联邦。



=== campaign/xor_gate/hint_0.txt ===

$15534865654723* 输入 0

$17025412277453* 输入 1

$59092390409834* 预期输出

$62308032073140* 输出为 [T]。

$84782011304318* 由真值表可知，当两路输入不同（[T][F] 或 [F][T]）时，



=== campaign/xor_gate/hint_solution.txt ===

$16623524168613* 请自行探索更好的解法吧！

$30671593085518* 这种解法不是最优雅或者最高效的。



=== campaign/xor_gate/label.txt ===

$22122562689406* 输出

$45326245069696* 输入



=== campaign/xor_gate/meta.txt ===

$21287008524643* 异或门（XOR）

$30005674935190*
这种电路叫做异或门（XOR gate）。这一关比前几关稍难一些，所以如果你没有立即找出解法，也请不必灰心。

[tip]你可以将一个逻辑门的输出连接到多个逻辑门的输入端上。[/tip]

$50002893048555* 上一关里，你搭建了一个只在第二个时钟周期输出 [T] 的电路。这一关里，你需要搭建一个在第二周期和第三周期都输出 [T] 的电路。



=== campaign/xor_gate/ui.txt ===

$38271404408184* 当前输出



=== model/board/custom_prototype.nim ===


# Default new output pin name for custom compoennts
$14864122622568* 输出


# Default new input pin name for custom compoennts
$14951951489108* 输入



=== model/board/prototype_list.nim ===


# com_mux's output pin
$10003014068713* 输出


# Component category name, at most 6 glyphs, the rest is cut off!
$10078663735607* 输入


# com_concatenator_8's input pin
$10080083255838* 第 3 组


# com_clz's output pin
$10092537578053* 输出


# com_splitter_bit_4's output pin
$10111764008386* 第 2 位


# com_level_output_4_pin's name
$10190739202646* 四路输出


# com_ctz's description
$10231593934948* 计算从最低位开始的连续零的位数


# com_xor_word's output pin
$10269927015049* 输出


# com_static_indexer_config's name
$10289043699917* 可调位宽静态索引器


# com_lsr's input pin
$10335381544532* 右移量


# com_halt's name
$10351143139905* 中断器


# com_nand_word's input pin
$10425218359878* 输入 0


# com_splitter_bit_8's description
$10488114435022* 将单字节输入拆分为八个二进制位


# com_splitter_bit_8's output pin
$10491931394044* 第 3 位


# Component category name, at most 6 glyphs, the rest is cut off!
$10495775939951* 输入/输出


# com_probe_wire_bit's input pin
$10499689720024* 待监测数值


# Component category name, at most 6 glyphs, the rest is cut off!
$10507478984775* 开发者


# com_splitter_bit_4's name
$10524104374521* 4 位分线器


# com_cc_output's name
$10557704838301* 输出端子


# com_segment_display's name
$10582128204153* 七段数码管


# com_switch_word's name
$10611658692685* 开关


# com_xnor_bit's description
$10614106399129* 当两路输入相同时输出 [T]


# com_not_word's description
$10624873506476* 将输入逐位取反


# com_counter's output pin
$10629272823895* 输出


# com_splitter_bit_2's output pin
$10655485270988* 第 0 位


# com_splitter_bit_8's output pin
$10688845521356* 第 1 位


# com_level_input_3_pin's name
$10689623552857* 三路输入


# com_maker_bit_8's input pin
$10716205698752* 第 5 位


# com_decoder_3's input pin
$10755367544042* 输入


# com_delay_line_word_config's output pin
$10757852071445* 输出


# com_rol's input pin
$10762061266647* 输入值


# com_decoder_2's output pin
$10762093809413* 第 1 位


# com_nor_word's input pin
$10770218762282* 输入 0


# com_concatenator_2's description
$10776829749898* 将最多 2 路输入按位首尾拼合为一路输出，输出位宽为各路输入位宽总和


# com_cc_output's description
$10781578424003* 为自定义元件添加输出引脚


# com_ror's description
$10802217509530* 对输入进行循环右移


# com_add's output pin
$10815269647822* 输出进位


# com_not_bit's description
$10844421681709*
对输入取反


# com_nand_word's description
$10859914201083* 对两路输入逐位执与非运算


# com_full_adder's output pin
$10918445419498* 输出（和）


# com_static_value's output pin
$10920459933396* 位宽值


# com_mod's description
$10934212906097* 对两路输入相除求余数


# com_level_input_word's name
$10943344093513* 输入


# com_keyboard's name
$10965596602414* 键盘


# com_less_s's output pin
$11019209691112* 输出


# com_asr's name
$11034107377099* 算术右移器


# com_maker_word_2's description
$11048127331082* 将 2 路 N/2 位输入值（位宽向下取整）拼合为一路 N 位的输出，输入中超出 N/2 位的部分将被忽略


# com_register_word_config's input pin
$11057152094224* 位宽指示线


# com_concatenator_8's input pin
$11115698874478* 第 0 组


# com_maker_bit_4's name
$11119510732154* 4 位集线器


# com_nand_bit's name
$11130919681688* 与非门（NAND）


# com_static_indexer_config's output pin
$11132082500971* 输出


# com_mux's description
$11168613697835* 在两路输入中选通一路


# com_full_adder's input pin
$11264799740288* 输入 0


# com_level_input_switched's name
$11278573510238* 三态输入


# com_not_word's name
$11286216680410* 按位非


# com_maker_word_2's output pin
$11293966912554* 输出


# com_decoder_2's output pin
$11297026031742* 第 2 位


# com_level_output_word's name
$11300749636961* 输出


# com_full_adder's input pin
$11312161634667* 输入 1


# com_delay_line_word_config's late input pin
$11320392055125* 输入


# com_mod's output pin
$11329013865174* 输出（余数）


# com_or_word's input pin
$11335506036805* 输入 1


# com_level_input_word's description
$11342065742485* 整型数值输入端子


# com_splitter_word_4's output pin
$11345730126879* 第 0 组


# com_static_indexer_config's input pin
$11349557191063* 输入


# com_maker_word_8's output pin
$11351867388170* 输出


# com_mod's input pin
$11352468367638* 被除数


# com_concatenator_8's input pin
$11366501215506* 第 2 组


# com_level_gate's name
$11417416554850* 关卡节点元件


# com_splitter_word_8's input pin
$11440186157356* 输入


# com_level_input_4_pin's name
$11447837612693* 四路输入


# com_inc's description
$11449663590476* 将输入加一后输出


# com_splitter_word_8's output pin
$11465347976002* 第 3 组


# com_level_output_switched's input pin
$11520072088720* 启用


# com_asr's output pin
$11521973612539* 输出


# com_splitter_bit_8's output pin
$11548514728473* 第 0 位


# com_switch_bit's name
$11574334638147* 开关


# com_nand_word's input pin
$11578787451669* 输入 1


# com_div's input pin
$11611913368782* 除数


# com_switch_word's output pin
$11625195403324* 输出


# com_maker_bit_8's input pin
$11634467729625* 第 4 位


# com_neg's input pin
$11637742665554* 输入


# com_clz's name
$11678932883790* 前导零计数器


# com_ram's name
$11710093917097* 内存


# com_decoder_2's name
$11727998752868* 2-4 译码器


# com_maker_bit_2's input pin
$11752209410617* 第 1 位


# com_and_word's description
$11791872137683* 对两路输入逐位执行与运算


# com_mul's output pin
$11838813794006* 输出


# com_off's name
$11860786587357* 低电平


# com_splitter_bit_8's name
$11904470559153* 8 位分线器


# com_nor_word's output pin
$11938328576163* 输出


# com_delay_line_bit's output pin
$11945697622944* 输出


# com_and_word's input pin
$11977039914327* 输入 0


# com_neg's description
$12021716182809* 计算输入值的相反数


# com_splitter_bit_2's input pin
$12046095993506* 输入


# com_screen's name
$12046117430308* 屏幕


# com_cc_level_output's description
$12051024347384* 整型数值输出端子。如果关卡解法被保存为自定义元件，该端子将成为元件的输出引脚。


# com_splitter_bit_4's input pin
$12060097589370* 输入


# com_xnor_word's name
$12087865653212* 按位同或


# com_ror's name
$12093087039542* 循环右移器


# com_delay_line_bit's name
$12121899638400* 延迟线


# com_nor_word's name
$12175906806727* 按位或非


# com_neg's output pin
$12196354295621* 输出


# com_level_output_1_pin's name
$12242923444593* 输出


# com_level_output_counter's name
$12247325526438* 计数器输出


# com_maker_word_4's output pin
$12262460678043* 输出


# com_probe_memory_bit's name
$12318534735397* 存储器探针（1 位）


# com_concatenator_2's input pin
$12329350771997* 第 2 组


# com_concatenator_8's input pin
$12341255296823* 第 1 组


# com_verilog_output's name
$12353364840899* Verilog 输出设备


# com_probe_wire_asm's late input pin
$12365938365321* 输入


# com_splitter_word_4's description
$12370556827575* 将输入的所有数位拆分到最多四条 N 位输出线路上


# com_concatenator_4's input pin
$12371272172145* 第 1 组


# com_concatenator_8's input pin
$12384635971036* 第 5 组


# com_decoder_3's output pin
$12390018918095* 第 7 位


# com_asr's input pin
$12408847893200* 右移量


# com_register_word's late input pin
$12420839132846* 待写入数值


# com_constant's description
$12424468899005* 输出一个整型常量


# com_concatenator_8's description
$12443053648819* 将最多 8 路输入按位首尾拼合为一路输出，输出位宽为各路输入位宽总和


# com_keyboard's output pin
$12465282633818* 键码


# com_level_input_1_pin's output pin
$12465938629713* 输入


# com_concatenator_8's output pin
$12478474747295* 输出


# com_probe_memory_word's description
$12492235992906* 用于将自定义元件中的存储器数值暴露在元件外表，或链接到汇编代码编辑器的监视槽上


# com_mux's input pin
$12520768681157* 输入 2


# com_switch_word's input pin
$12550214308917* 输入


# com_maker_word_8's input pin
$12592072659210* 第 1 组


# com_maker_bit_2's name
$12602955212919* 2 位集线器


# com_maker_word_8's input pin
$12616927929524* 第 3 组


# com_static_indexer_config's input pin
$12633414511976* 输出位宽指示线


# com_delay_line_word's late input pin
$12644592179746* 输入


# com_register_bit's name
$12678278048629* 寄存器


# com_mux's input pin
$12687047365426* 输入 1


# com_and_bit's description
$12719674432950*
两路输入均为 [T] 时输出 [T]


# com_splitter_word_2's name
$12723870092766* 2 路分线器


# com_counter's description
$12736827510023* 不擦写时，存储和输出的数值每周期递增


# com_level_input_1_pin's name
$12746117288689* 输入


# com_off's description
$12749460799924* 始终输出 [F]


# com_less_s's description
$12765625016236* 判断第一路输入是否小于第二路（输入视作有符号整数）


# Component category name, at most 6 glyphs, the rest is cut off!
$12778241216484* 布尔


# com_switch_word's input pin
$12784430582183* 导通/断开


# com_lsl's input pin
$12849468178655* 输入值


# com_static_indexer_config's input pin
$12869119410565* 偏移位宽指示线


# com_nand_bit's description
$12903183841172*
仅两路输入均为 [T] 时输出 [F]


# com_and_word's name
$12926911335769* 按位与


# com_lsr's name
$12931148241340* 逻辑右移器


# com_splitter_word_4's input pin
$12938882109013* 输入


# Component category name, at most 6 glyphs, the rest is cut off!
$12972244522540* 显示


# com_halt's description
$12990744955549* 激活时中断计算机运行，并输出一条自定义消息


# com_or_bit's description
$13013154620359*
任意一路输入为 [T] 时输出 [T]


# com_level_output_8_pin's name
$13087193858087* 8 路输出


# com_maker_bit_8's input pin
$13104890311933* 第 1 位


# com_rol's input pin
$13135722015590* 左移量


# com_decoder_3's output pin
$13138546420646* 第 6 位


# com_store_port's name
$13159020985209* 写入端口


# com_level_delay_gate's name
$13161432526100* 关卡节点元件（含延迟量）


# com_level_output_3_pin's description
$13174121812559* 包含 3 位的输出端子


# com_maker_word_4's input pin
$13236424504117* 第 2 组


# com_xor_word's description
$13236921580268* 对两路输入逐位执行异或运算


# com_level_output_2_pin's name
$13255344581755* 二路输出


# com_level_gate's description
$13259215761047* 在关卡树上新增关卡


# com_cc_input's description
$13263310288543* 为自定义元件添加输入引脚


# com_delay_line_word_config's input pin
$13271299225650* 位宽指示线


# com_level_input_1_pin's description
$13272198916233* 仅包含 1 位的输入端子


# com_register_word's late input pin
$13298317818150* 写入


# com_concatenator_4's input pin
$13331778821779* 第 0 组


# com_verilog_input's output pin
$13351141217116* 读取的数值


# com_nor_bit's name
$13375115196253* 或非门（NOR）


# com_maker_word_8's input pin
$13378739117488* 第 6 组


# com_less_u's name
$13502755965496* 无符号小于


# com_splitter_word_2's output pin
$13510688527850* 第 1 组


# com_ror's input pin
$13521735131997* 右移量


# com_register_word's description
$13576980017857* 低容量存储元件


# com_splitter_word_2's output pin
$13625849577132* 第 0 组


# com_splitter_bit_8's output pin
$13666042416530* 第 2 位


# com_keyboard's output pin
$13705122401876* 事件队列非空


# com_splitter_bit_2's name
$13766521376720* 2 位分线器


# com_maker_bit_4's input pin
$13826250945595* 第 3 位


# com_ctz's input pin
$13829181406158* 输入


# com_equal's input pin
$13859686951415* 输入 0


# com_add's name
$13973952772642* 加法器


# com_xnor_bit's name
$14079327237795* 同或门（XNOR）


# com_lsl's output pin
$14132199132916* 输出


# com_less_u's input pin
$14201184715010* 输入 0


# com_maker_bit_4's input pin
$14237744302250* 第 0 位


# com_keyboard's output pin
$14338437722935* 键位按下/弹起


# com_maker_bit_8's description
$14338505460996* 将八个二进制为合并为一路单字节整数线


# com_level_input_2_pin's description
$14340334686746* 包含 2 位的输入端子


# com_decoder_3's name
$14375716460090* 3-8 译码器


# com_verilog_input's description
$14408471620057* 电路被导出为 Verilog 文件时，该元件会被转写为输入信号


# Component category name, at most 6 glyphs, the rest is cut off!
$14422565604875* 集线


# com_probe_wire_word's name
$14427436420428* 线路探针


# com_not_bit's name
$14453052824732* 非门（NOT）


# com_inc's name
$14456039381703* 递增器


# Component category name, at most 6 glyphs, the rest is cut off!
$14485213322089* Verilog


# com_nor_word's description
$14517798310461* 对两路输入逐位执行或非运算


# com_maker_bit_2's description
$14531866237078* 将两个二进制位合并为一路 2 位整数线


# com_splitter_word_8's output pin
$14592399073683* 第 7 组


# com_splitter_bit_4's output pin
$14645527447275* 第 0 位


# Component category name, at most 6 glyphs, the rest is cut off!
$14686892562446* 内存


# com_decoder_3's output pin
$14688114733776* 第 5 位


# com_maker_bit_8's input pin
$14770992007366* 第 6 位


# com_maker_word_2's name
$14812135740513* 2 路集线器


# com_xor_bit's name
$14832952840086* 异或门（XOR）


# com_register_bit's output pin
$14834136969633* 输出


# com_maker_bit_2's input pin
$14834270613682* 第 0 位


# com_segment_display's input pin
$14849689592952* 输入


# com_maker_bit_4's input pin
$14852108377004* 第 2 位


# com_level_output_2_pin's description
$14875690243444* 包含 2 位的输出端子


# com_maker_bit_8's output pin
$14889574903079* 输出


# com_mul's input pin
$14896244080868* 输入 0


# com_mul's input pin
$14913258317738* 输入 1


# com_probe_wire_word's input pin
$14914933156268* 待监测数值


# com_level_input_switched's input pin
$14935676453720* 启用/禁用


# com_maker_bit_8's input pin
$14944669923906* 第 7 位


# com_div's name
$14959426271423* 除法器


# com_verilog_output's description
$14973155280765* 电路被导出为 Verilog 文件时，该元件会被转写为输出信号


# com_less_u's output pin
$15024221028085* 输出


# com_mux's input pin
$15091015683874* 选通第一路/第二路


# com_asr's description
$15194709458499* 对输入进行右移，并保持符号不变


# com_probe_wire_bit's description
$15206117280094* 用于将自定义元件中特定线路的数值暴露在元件外表，或链接到汇编代码编辑器的监视槽上


# com_splitter_word_8's description
$15228522216068* 将输入的所有数位拆分到最多八条 N 位输出线路上


# com_maker_word_4's input pin
$15232070727738* 第 1 组


# com_lsl's name
$15268915597774* 逻辑左移器


# com_inc's output pin
$15310910823919* 输出


# com_splitter_word_4's output pin
$15360783001914* 第 2 组


# com_less_s's name
$15403981009644* 有符号小于


# com_maker_word_4's description
$15410415450178* 将 4 路 N/4 位输入值（位宽向下取整）拼合为一路 N 位的输出，输入中超出 N/4 位的部分将被忽略


# com_splitter_word_2's description
$15417695246232* 将输入的所有数位拆分到最多两条 N 位输出线路上


# com_mux's name
$15422378975821* 数据选择器


# com_less_s's input pin
$15432695156488* 输入 0


# com_concatenator_4's description
$15492861320167* 将最多 4 路输入按位首尾拼合为一路输出，输出位宽为各路输入位宽总和


# com_decoder_3's output pin
$15527856774069* 第 2 位


# com_rol's description
$15557725551789* 对输入进行循环左移


# com_splitter_word_4's output pin
$15566912320742* 第 1 组


# com_cc_level_output's name
$15625973306519* 输出端子


# com_not_word's output pin
$15635980858172* 输出


# com_level_output_8_pin's input pin
$15649241608462* 输出 6


# com_equal's description
$15668435514829* 判断两路输入是否相等


# com_maker_word_4's input pin
$15693531522415* 第 0 组


# com_splitter_bit_4's output pin
$15744234453408* 第 3 位


# com_concatenator_8's input pin
$15759275278695* 第 4 组


# com_ror's input pin
$15762072154176* 输入值


# com_xnor_word's description
$15789912406647* 对两路输入逐位执行同或运算


# com_static_value's output pin
$15833633678405* 位宽指示线


# com_maker_word_8's description
$15845204308823* 将 8 路 N/8 位输入值（位宽向下取整）拼合为一路 N 位的输出，输入中超出 N/8 位的部分将被忽略


# com_constant's name
$15858905835416* 常量


# com_on's name
$15896157427528* 高电平


# com_decoder_2's output pin
$15898724303882* 第 3 位


# com_concatenator_4's name
$15908922745328* 4 路并线器


# com_or_word's input pin
$15962339721851* 输入 0


# com_probe_wire_word's description
$15969687819995* 用于将自定义元件中特定线路的数值暴露在元件外表，或链接到汇编代码编辑器的监视槽上


# com_clz's input pin
$15988469904002* 输入


# com_register_word's name
$16007777261800* 寄存器


# com_time's name
$16011300295966* 系统时间


# com_splitter_word_4's output pin
$16099286786157* 第 3 组


# com_static_indexer's description
$16103423834548* 将线路上的值偏移固定的位数后输出。正偏移量表示右移，负偏移量表示左移。此元件不产生开销。


# com_lsr's input pin
$16105779236896* 输入值


# com_less_s's input pin
$16118461327893* 输入 1


# com_splitter_word_8's output pin
$16120663256468* 第 4 组


# com_level_output_word's description
$16148744080822* 整型数值输出端子。如果关卡解法被保存为自定义元件，该端子将成为元件的输出引脚。


# com_maker_word_2's input pin
$16178897760565* 第 1 组


# com_splitter_bit_8's input pin
$16196769003341* 输入


# com_on's description
$16212935718484* 始终输出 [T]


# com_mod's name
$16223673009720* 模余器


# com_level_output_4_pin's input pin
$16259545926196* 输出 0


# com_ror's output pin
$16261916666444* 输出


# com_level_output_3_pin's name
$16269858195218* 三路输出


# com_static_eval's name
$16294314784377* 静态位宽解算器


# com_less_u's input pin
$16307028951926* 输入 1


# Component category name, at most 6 glyphs, the rest is cut off!
$16316545288606* 逻辑


# com_load_port's name
$16380513614754* 读取端口


# com_counter's late input pin
$16380665909610* 覆写计数器


# com_splitter_bit_4's description
$16428357982878* 将半字节输入拆分为四个二进制位


# com_load_port's description
$16440979564796* 为内存元件添加一个读取端口


# com_concatenator_4's output pin
$16450922709110* 输出


# com_lsl's description
$16482114876737* 对输入进行按位左移


# com_mul's name
$16549841656852* 乘法器


# com_add's output pin
$16559516323162* 输出（和）


# com_splitter_word_4's name
$16563671560208* 4 路分线器


# com_level_input_3_pin's description
$16604606953092* 包含 3 位的输入端子


# com_maker_word_4's name
$16610055905190* 4 路集线器


# com_decoder_3's output pin
$16637198920534* 第 1 位


# Component category name, at most 6 glyphs, the rest is cut off!
$16656763610465* 输出


# com_xor_word's input pin
$16674052164634* 输入 0


# Component category name, at most 6 glyphs, the rest is cut off!
$16684378975952* 自定义


# com_decoder_1's description
$16685462633615* 在 2 路输出中选通一路


# Component category name, at most 6 glyphs, the rest is cut off!
$16744990871521* 关卡元件


# com_rol's name
$16755142829250* 循环左移器


# com_segment_display's description
$16761198694928* 显示数字的便利设备


# com_keyboard's description
$16766452660421* 记录来自键盘的按键事件


# com_decoder_3's input pin
$16773243310913* 禁用


# com_level_input_switched's description
$16797889673362* 读取关卡测例的输入值


# com_and_word's output pin
$16806711173957* 输出


# com_cc_level_input's name
$16810631435170* 输入端子


# com_and_3_bit's description
$16839706221116* 带有三路输入的与门


# com_xor_word's name
$16843812162355* 按位异或


# com_xor_bit's description
$16856280609387*
当两路输入不同时输出 [T]


# com_level_input_2_pin's name
$16870364449392* 二路输入


# com_static_eval's description
$16874064281189* 对输入的两路指示线的位宽值进行算术操作，以解算新位宽。解算在电路仿真开始前完成，输出线路位宽在电路运行过程中保持固定。


# com_probe_memory_bit's description
$16875362121056* 用于将自定义元件中的存储器数值暴露在元件外表，或链接到汇编代码编辑器的监视槽上


# Component category name, at most 6 glyphs, the rest is cut off!
$16900787805858* 整型


# com_switch_bit's description
$16917313833836* 控制单根导线通断


# com_concatenator_8's name
$16974631589430* 8 路并线器


# com_cc_level_output's input pin
$17030391013189* 输出


# com_splitter_bit_8's output pin
$17053062486634* 第 4 位


# com_or_word's name
$17053670145576* 按位或


# com_xnor_word's output pin
$17089816656649* 输出


# com_decoder_3's output pin
$17090003684860* 第 4 位


# com_splitter_bit_8's output pin
$17163920171569* 第 6 位


# com_static_value's name
$17192199509688* 静态位宽指示器


# com_store_port's description
$17240636780043* 为添加一个额外的写入端口


# com_mod's input pin
$17244932190980* 除数


# com_or_bit's name
$17247779246257* 或门（OR）


# com_splitter_bit_2's output pin
$17293853955838* 第 1 位


# com_switch_word's description
$17345192339084* 控制输入值是否连通到输出端


# com_delay_line_word's name
$17407828844862* 延迟线


# com_splitter_word_8's output pin
$17425893786880* 第 6 组


# com_concatenator_2's name
$17495243848605* 2 路并线器


# com_nor_bit's description
$17510848535619*
仅两路输入均为 [F] 时输出 [T]


# com_maker_bit_8's input pin
$17515061804367* 第 0 位


# com_full_adder's description
$17559382166174* 将 3 路输入相加，输出总和与进位


# com_or_3_bit's description
$17576327690867* 带有三路输入的或门


# com_maker_word_8's name
$17581447274882* 8 路集线器


# com_register_word_config's name
$17630501850089* 可调位宽寄存器


# com_level_output_3_pin's input pin
$17644027370563* 输出 2


# com_splitter_bit_8's output pin
$17664445405251* 第 5 位


# com_full_adder's name
$17669928463861* 全加器


# com_register_bit's description
$17670626909848* 一位存储器


# com_maker_word_4's input pin
$17742753106024* 第 3 组


# com_register_bit's late input pin
$17744526831576* 写入


# com_concatenator_2's output pin
$17758165407719* 输出


# com_counter's late input pin
$17764401720104* 待写入数值


# com_equal's input pin
$17767800149691* 输入 1


# com_static_value's description
$17781742628050* 在自定义元件表面添加位宽设置窗，并将接收的静态位宽发送到输出线路和位宽指示线上，以供元件计算或调整位宽使用。


# com_add's input pin
$17802619460312* 输入进位


# com_cc_input's name
$17814826739168* 输入端子


# com_add's input pin
$17820183531095* 输入 0


# com_splitter_bit_4's output pin
$17862413256378* 第 1 位


# com_equal's output pin
$17864898529357* 输出


# com_maker_bit_4's input pin
$17897455882076* 第 1 位


# com_store_port's input pin
$17908666907710* 待写入数值


# com_concatenator_8's input pin
$17908668221433* 第 7 组


# com_maker_bit_8's input pin
$17957417956069* 第 3 位


# com_level_output_switched's input pin
$17979647868788* 输出


# com_load_port's output pin
$17988237627670* 输出


# com_nand_word's name
$17989404583269* 按位与非


# com_store_port's input pin
$18001316449428* 写入地址


# com_counter's name
$18007194288764* 计数器


# com_splitter_word_8's name
$18008204445107* 8 路分线器


# com_add's input pin
$18009367936916* 输入 1


# com_div's input pin
$18043895181775* 被除数


# com_maker_bit_2's output pin
$18060429242565* 输出


# com_probe_wire_asm's late input pin
$18082830776248* 地址


# com_not_word's input pin
$18100827224098* 输入


# com_and_word's input pin
$18149321315676* 输入 1


# Component category name, at most 6 glyphs, the rest is cut off!
$18160228892566* 外设


# com_keyboard's input pin
$18168295822085* 读取下一个键盘事件


# com_store_port's input pin
$18196820862263* 写入


# com_delay_line_bit's description
$18206009264853* 将输入保留一周期后输出


# com_decoder_3's output pin
$18208851966397* 第 3 位


# com_decoder_1's name
$18250587600120* 1-2 译码器


# com_level_output_2_pin's input pin
$18282543476901* 输出 0


# com_level_output_4_pin's description
$18308856504509* 包含 4 位的输出端子


# com_level_output_switched's description
$18319747827404* 带有启用引脚的输出设备


# com_level_output_1_pin's description
$18342586404936* 仅包含 1 位的输出端子


# com_maker_word_2's input pin
$18365137610205* 第 0 组


# com_neg's name
$18379907297327* 取反器


# com_load_port's input pin
$18399493738021* 读取


# com_register_bit's late input pin
$18405644304073* 待写入的值


# com_full_adder's output pin
$18410639135888* 输出进位


# com_concatenator_2's input pin
$18414950181373* 第 1 组


# com_splitter_word_8's output pin
$18425501753807* 第 0 组


# com_add's description
$18429814030509* 对两路输入求和


# com_splitter_bit_8's output pin
$18437214963047* 第 7 位


# com_delay_line_word_config's description
$18447417990806* 将输入保留一周期后输出


# com_full_adder's input pin
$18480011054605* 输入进位


# com_probe_memory_word's name
$18495107507052* 存储器探针


# com_time's output pin
$18510923212418* 自 1970 年元旦以来的总纳秒数


# com_maker_bit_4's output pin
$18538545767544* 输出


# com_splitter_word_8's output pin
$18541722201520* 第 2 组


# com_asr's input pin
$18563543025377* 输入值


# com_splitter_bit_2's description
$18566798809283* 将 2 位输入拆分成两个二进制位


# com_register_word_config's late input pin
$18592599175225* 待写入数值


# com_or_word's output pin
$18599325743999* 输出


# com_nand_word's output pin
$18604301487974* 输出


# com_mul's description
$18631919890554* 对两路输入求积


# com_less_u's description
$18645721548287* 判断第一路输入是否小于第二路（输入视作无符号整数）


# com_maker_word_8's input pin
$18747558269936* 第 7 组


# com_maker_bit_8's name
$18747779812970* 8 位集线器


# com_time's description
$18774996925434* 自 1970 年元旦以来经过的纳秒数


# com_maker_bit_4's description
$18837875001662* 将四个二进制位合并为一路 4 位整数线


# com_clz's description
$18865460617183* 计算从最高位开始的连续零的位数


# com_and_bit's name
$18912167455465* 与门（AND）


# com_concatenator_4's input pin
$18970466583796* 第 2 组


# com_decoder_3's output pin
$19041825668970* 第 0 位


# com_level_output_counter's description
$19047791955795* 包含 3 位的输出端子


# com_maker_word_8's input pin
$19068496076705* 第 2 组


# com_load_port's input pin
$19069820293504* 读取地址


# com_concatenator_8's input pin
$19112189486457* 第 6 组


# com_lsl's input pin
$19120200575252* 左移量


# Component category name, at most 6 glyphs, the rest is cut off!
$19169839564869* 探针


# com_level_input_4_pin's description
$19187328896214* 包含 4 位的输入端子


# com_register_word_config's description
$19209488297941* 可通过指示线自动调整位宽的寄存器


# com_maker_bit_8's input pin
$19209724501083* 第 2 位


# com_ctz's name
$19218324472471* 尾随零计数器


# com_splitter_word_8's output pin
$19229992367375* 第 5 组


# com_div's description
$19251828025705* 对两路输入相除求商


# com_decoder_2's output pin
$19275565166747* 第 0 位


# com_verilog_output's input pin
$19276197821142* 待写入的值


# com_concatenator_4's input pin
$19277763516215* 第 3 组


# com_xnor_word's input pin
$19329533997829* 输入 0


# com_nor_word's input pin
$19354802063529* 输入 1


# com_equal's name
$19369982838671* 判等器


# com_lsr's description
$19394421220436* 对输入进行按位右移


# com_div's output pin
$19403575811053* 输出（商）


# com_or_word's description
$19406015796751* 对两路输入逐位执行或运算


# com_delay_line_word_config's name
$19421095581293* 可调位宽延迟线


# Component category name, at most 6 glyphs, the rest is cut off!
$19451948914812* 算术


# com_level_output_switched's name
$19513138880387* 三态输出


# com_probe_wire_bit's name
$19521764791439* 线路探针（1 位）


# com_maker_word_8's input pin
$19579002124406* 第 4 组


# com_inc's input pin
$19579388993928* 输入


# com_xnor_word's input pin
$19579585753615* 输入 1


# com_or_3_bit's name
$19630419947500* 三路或门


# com_splitter_word_2's input pin
$19630801846451* 输入


# com_and_3_bit's name
$19664974941910* 三路与门


# com_register_word_config's late input pin
$19717901345023* 写入


# com_xor_word's input pin
$19719622211817* 输入 1


# com_maker_word_8's input pin
$19740232065347* 第 0 组


# com_lsr's output pin
$19748092068880* 输出


# com_maker_word_8's input pin
$19779691531031* 第 5 组


# com_verilog_input's name
$19796166910463* Verilog 输入设备


# com_static_indexer's name
$19804933576629* 静态索引器


# com_ram's description
$19814732518166* 高容量存储元件


# com_cc_level_input's description
$19864966939331* 整型数值输入端子。如果关卡解法被保存为自定义元件，该端子将成为元件的输入引脚。


# com_ctz's output pin
$19883191600386* 输出


# com_splitter_word_8's output pin
$19903808503639* 第 1 组


# com_rol's output pin
$19903955254861* 输出


# com_screen's description
$19974317694842* 可配置功能的显示屏


# com_push_button's name
$20020953885936* 按钮开关


# com_level_output_3_pin's input pin
$21084166025569* 输出 1


# com_level_input_word's output pin
$21448308897245* 输入


# com_level_input_2_pin's output pin
$24473197268827* 输入 0


# com_probe_wire_asm's description
$27381538627533* 依据当前使用的指令集，对输入线路上的数值进行反汇编，并显示原始指令。


# com_level_output_word's input pin
$27680966493404* 输出


# com_level_output_4_pin's input pin
$29217965518477* 输出 1


# com_static_eval's output pin
$29937009351190* 解算位宽（指示线）


# com_level_input_4_pin's output pin
$36196915566111* 输入 3


# com_level_output_8_pin's input pin
$38015555977208* 输出 3


# com_level_output_4_pin's input pin
$39260627694444* 输出 3


# com_level_output_8_pin's input pin
$39299381405096* 输出 0


# com_level_output_3_pin's input pin
$39908016538045* 输出 0


# com_delay_line_word's output pin
$40182352594863* 输出


# com_level_output_8_pin's description
$41781588125341* 包含 8 位的输出端子


# com_level_input_3_pin's output pin
$42291627335021* 输入 2


# com_delay_line_bit's late input pin
$43397945955203* 输入


# com_level_output_2_pin's input pin
$44555908976270* 输出 1


# com_level_input_4_pin's output pin
$45891070331034* 输入 1


# com_level_output_1_pin's input pin
$50802766489958* 输出


# com_probe_wire_asm's name
$53494192640542* 反汇编探针


# com_delay_line_word's description
$53901484249817* 将输入保留一周期后输出


# com_screen's input pin
$55023356915123* 要改写的选项


# com_level_input_2_pin's output pin
$55925432534232* 输入 1


# com_push_button's description
$57617462098732* 鼠标按下时输出 [T]，松开时输出 [F]


# com_register_word's output pin
$58518173140953* 输出


# com_cc_level_input's output pin
$59388037506003* 输入


# com_decoder_3's description
$61176454433312* 根据输入的 3 位数值，在 8 路输出中选通对应的一路


# com_level_output_8_pin's input pin
$62385154489080* 输出 2


# com_screen's input pin
$63216408139965* 写入设置（接收输入）


# com_level_delay_gate's description
$64425234668581* 用于在关卡图上创建新关卡。该元件带有一个额外的引脚，用于输出所有解法中最低的延迟量。


# com_level_output_8_pin's input pin
$64999131838438* 输出 4


# com_level_input_3_pin's output pin
$65765566466116* 输入 0


# com_level_input_switched's output pin
$69212597107829* 输入


# com_level_input_4_pin's output pin
$70142958857584* 输入 2


# com_level_output_8_pin's input pin
$72375982885383* 输出 1


# Component category name, at most 6 glyphs, the rest is cut off!
$75263091584586* 可调位宽


# com_level_input_3_pin's output pin
$79311371309532* 输入 1


# com_level_input_4_pin's output pin
$81933801309767* 输入 0


# Component category name, at most 6 glyphs, the rest is cut off!
$82535571951563* 杂项


# com_level_output_counter's input pin
$84023157447564* 第 0 位


# com_register_word_config's output pin
$84598344098990* 输出


# com_static_indexer_config's description
$85065774878853* 可自动调整位宽的静态索引器。其偏移量和输出位宽都可由相连的位宽指示线确定。


# com_level_output_counter's input pin
$86331851878040* 第 1 位


# com_decoder_2's description
$86848277190736* 根据输入的 2 位数值，在 4 路输出中选通对应的一路

$87754378235471* 输出


# com_level_output_4_pin's input pin
$87954408093587* 输出 2


# com_screen's input pin
$88137790657923* 要改写的值


# com_level_output_8_pin's input pin
$88250281919265* 输出 5


# com_static_eval's output pin
$89594489498667* 解算结果（值）


# com_level_output_counter's input pin
$89669851602178* 第 2 位


# com_level_output_8_pin's input pin
$90233476470983* 输出 7



=== model/isa_spec/assemble.nim ===

$12097260550100* 数值 {num} 已超出 {field} 许可的范围

$15585581119466* 指令'{instruction_name}'缺少有效的位模式

$15728875852508* 文件 {file} 解析失败

$18981788561705* 此处应有空格

$19131785861372* 检测到文件循环包含：

$19581803133960* 指令不完整：'{partial_instruction}'之后应有'{syntax}'

$21828993759952* 未知指令

$23413102374088* 无效指令

$30066682696902* 断言 {source} 匹配失败

$33085034295813* 此处应有数值或已定义的名称

$35071857261934* 'as'后应有空白字符

$35210741057769* 无法解析此行内容

$37770431994640* 无效指令

$39195841380612* 标签 {name} 被重复定义

$42442531119863* 常量 {constant_name} 被重复定义

$45433710484419* 数字前应有字长标记，例如'U64 {number}'

$47300717145684* 'const'后缺少'='

$48895355188042* '@'后应紧随常数字面值

$51460031660101* 编译指令时解析标签'{name}'失败：{err}

$51466436379956* 补位填充只能前向进行。当前地址：{address}

$53378617686677* 数值 {num} 已超出 {field} 许可的范围

$57794055991905* 检查断言 {assertion} 时发生错误：{err}

$58979769991732* 包含文件名之后应另起新行

$59248806788382* 无法引用私有标签 {name}

$60515742509356* 字长之后应为一个数值

$60631582636278* 标签 {name} 尚未定义

$62050046600010* 文件名 {name} 不是合法的作用域名称。请用关键字'as'为其定义一个别名，例如'include .A as A'

$66273157704409* 此处缺少'{field_type}'类型的操作数

$66575346967082* 指定的文件不存在：

$67922577781529* 目前仅支持使用 8 的正整数倍作为字长

$68530592279217* 此处应填写有效的操作数名称，但输入值为'{operand_name}'（操作数列表为 {all_operand_names}）

$69537550553443* '{partial_instruction}'后应有空白字符

$71714150108621* 计算操作数 %{operand_name} 时发生错误：{err}

$76017808702292* 指令'{instruction_name}'的字长为 {width} 位，当前版本仅支持 8 的整数倍指令字长。

$79977943868423* '{field_string}'不是'{field_type}'

$80097289956044* 字长和数字之间应有空白字符，例如'U{size} {number}'

$82512572175623* 指令'{partial_instruction}'不完整（意外结束）

$83023561541280* 此处应为标签名称

$83649060120708* 不支持使用有符号数值

$84557608492963* 指令之后出现未知代码：

$86607635528717* 常量 {field_string} 未定义

$87525828760679* 解析宏模式'{resolved_pattern}'失败（{err}）

$90294506138532* 定义必须是一个常数或枚举值



=== model/isa_spec/expressions.nim ===

$14037712136328* 未找到操作数 {op}

$15525193700799* 无法识别前缀运算符

$16677833364088* 无法识别标识符：%{operand}

$17795651801484* 此处应有':'

$18996202754936* 此处应有')'

$21791372106633* 此处应有 '('

$36919792698704* 指令指针不可用

$49919016022369* 无法识别地址：${identifier}

$50863314907270* 此处应有 ')'

$62520916869207* 此处应有 ','

$76203559781109* 此处应有']'或':'，但当前检测到'{sep}'

$86940018019179* 标识符无效：%{operand}



=== model/isa_spec/isa_spec.nim ===

$11703098452145* 未知的设置项 {name}

$11824708197936* 此处应为有效的枚举域或宏模式名称，但当前填入的内容为'{operand_name}'

$15904571494199* 输出位模式中引用枚举域或宏模式时必须使用位切片

$16564670893367* 此处应为宏模式名称

$18247681204565* 断言结尾处应有')'

$18304638469397* 行注释应以非空字符串开始

$19678805612580* 对同一枚举域的重复引用出错

$20574862674671* 虚拟操作数之后应另起新行

$20981379307111* %{operand} 中的固定位模式匹配错误

$23037984432484* 'when'条件表达式之后应有':'

$24713798894610* 位切片上界不能超过 32767

$25123045290962* 此处应有指令区段的标题'[instructions]'

$25249187420360* 此处应为设置选项的名称或指令集下一个区段的标题

$25285447732570* 上界不能小于下界

$26426549472884* 虚拟操作数过多

$27111936748508* 宏模式列表应以右括号')'结束

$28197258085607* 输出位模式中引用枚举域或宏模式时必须使用位切片

$29837913233106* 指令之间应另起新行

$31223930569837* 上界不能小于下界

$32763965727763* 符号扩展位匹配错误

$33105996916812* 宏模式只能调用在自身之前已被定义的宏模式

$33504435568130* 无法解析虚拟操作数 %{variable_name}：{err}

$33645913580119* 枚举域数量超出限制（最大值为 {max_field_types}）

$33890983338825* 此处应为一个字符串表

$35053289858864* 宏模式数量超出限制（最大值为 {max_patterns}）

$35468867558322* 区段起始标记之后必须另起一行

$39427635035157* 设置项'{name}'已被赋值

$40392382190976* 枚举值 {field_name} 的定义应为二进制位模式

$40815956642962* 输出位模式中引用十六进制值时必须使用位切片

$42160516340132* 操作数名称后需紧跟圆括号或方括号，例如 {variable_name}(immediate) 或 {variable_name}[pattern()]

$42907704133778* 宏模式参数列表结尾处须有')'

$43708359021513* 宏模式签名后必须有定义

$45247724910259* 操作数的取值超出 {n} 位无符号整型范围

$45267257140327* 区段起始标记之后必须另起一行

$45631078896174* 位切片上界不能超过 32767

$47258389995911* 宏模式参数之间须以','分隔

$48321097736953* 十六进制字面值不能超过 32767 位

$48639756889210* 指令位宽不能为零

$48942522553057* 输出位模式中引用枚举域或宏模式时必须使用位切片

$50971737349470* 反汇编暂不支持解析宏模式操作数

$51752498682665* 枚举域'{field_name}'尚未定义

$52261961290701* 输出位模式中引用十六进制值时，位切片语法倒错

$52710717731997* 语法定义之后应另起新行

$55289908013299* 语法行中的虚拟操作数 {variable_name} 与其它操作数发生名称冲突

$55444523984237* 枚举域列表应以右括号')'结束

$55537815420873* 宏模式参数后应有','或')'

$55929094649794* 此处应为一个字符串表

$56352157276583* 操作数的取值超出 {n} 位有符号整型范围

$57773886232356* 定义枚举值之前必须指定枚举域的名称

$58295598661589* 宏模式的描述必须留空

$59115040206693* 块注释须以非空字符串开头

$59388744207582* 位模式之后应另起新行

$59877879891546* 无法解析'when'条件表达式：{err}

$61352853872444* 此处立即数的位数须介于 0 至 {max_field_size} 之间

$61772889138477* 宏模式参数列表前应有'('

$62103010038950* 区段起始标记之后必须另起一行

$62334191081955* 输出位模式中引用十六进制值时必须使用位切片

$62712568576067* 枚举域 {name} 被重复定义

$63072912015761* 宏模式定义须另起一行

$63246722572594* 位模式中引用枚举域全名时必须使用位切片语法

$63957561177031* 找不到带有 {argument_count} 个参数的宏模式'{pattern_name}'定义

$64093416909416* '%'之后应紧接一个标识符

$67219559926029* 枚举域名称不能包含空白字符

$67707174963301* '%'之后应紧接一个标识符

$68066163358870* 'when'之后应有空白字符

$68462760531745* 枚举值 {field_name} 的位模式包含 {actual} 个二进制位，但期望的位数为 {expected}

$68533544457789* 语法行中的操作数 {variable_name} 与其它操作数发生名称冲突

$68587613470552* 此处应有枚举值

$70205284263092* 块注释须以非空字符串收束

$70814401439344* 位切片上界不能小于下界

$72400465574342* 枚举域的位宽不能超过 {max_field_width} 位

$72620639818015* 区段起始标记之后必须另起一行

$72958581072457* 宏模式须有名称

$73627734748417* 宏模式名称前应有 pattern 关键字

$75146029145419* 宏参数须有名称

$76494975412451* 此处应填写有效的操作数名称，但输入值为'{operand_name}'（操作数列表为 {all_operand_names}）

$77234329031993* 输出位模式中引用枚举域或宏模式时必须使用位切片

$77449878176461* '%'之后应紧接一个标识符

$77851254343918* 没有找到任何以'{c}'开头的操作数

$78591996283483* 此处应有枚举域名称或定长立即数

$79195048703101* 此处应有'='

$79975911393070* 输出位模式中引用枚举域或宏模式时必须使用位切片

$81691406697268* 引用枚举域的位切片必须指定上界（切片最高位）

$82876816015252* 自动反汇编的操作数选项路径过多，最多允许 {num_path} 条路径

$83804207975330* 位切片上界不能超过 32767

$85972591916322* 设置之后需另起一行

$87843223218582* 指令字长为 {width} 位，当前版本仅支持 8 的整数倍指令字长

$90809893168338* 立即数类型的操作数前须有位宽指示符，例如：%a:U8(immediate)



=== model/isa_spec/parse.nim ===

$10198498286711* 转义序列不完整

$11064758781325* UI 单元格内容需以'"'、'''或'`'开头

$12492443144951* 此处应有','或数据表结尾标识

$13040813748160* 键对定义应包含键名

$19807940646400* 此处应有 {expected} 之一，但当前值为 {actual}

$22378976352410* 第 {num} 行：

$22452670489981* 此处应为常数字面值

$25983481845150* 此处应为 '{symbol}'，但文件已到达结尾（EOF）

$27682737127628* 此处应有左引号（"/'/` 之一）

$29112746104375* 此处应为布尔（逻辑）值

$33400766069212* 此处应有左括号（'('、'['或'{{'之一），但当前输入的是'{open}'

$33551107641907* 整型字面值过大

$36313699368590* 无效的八进制转义序列

$43326454052643* 数字开头应有'S'或'U'（分别对应有符号与无符号字面值）

$44942745729831* 无效的十六进制转义序列

$49180229055343* 键对定义应包含键值

$51855228989260* 无效的无符号整型字面值

$56457570130031* 转义字符'{nc}'无效

$64743950507593* 此处应为一个列表对象

$64926004981217* 整数字面值无效

$66187706284192* 键对名称后应有':'

$71666516845083* 此处应为无符号字面值

$72110029133381* 此处应有 {prefix}

$73113688099439* 此处应有 {expected} 之一

$73973243772156* 此处应为有符号字面值

$75565287060042* 解析字符串时意外遇到文件结尾（EOF）

$77089554485217* 此处应有长度声明

$82386938622647* 转义字符'\\'之后应有对应的转义文本



=== model/isa_spec/types.nim ===

$12246885387560* 变量 {name}


# Assembly label
$17885987456433* 标签

$18299156828551* 有符号 {n} 位立即数

$74639900282369* 无符号 {n} 位立即数



=== model/translations.nim ===

$11567406591202* 1 字节

$14036822471924* {days} 天前

$16391754618645* {size} KB

$17901039729248* {months} 个月前

$18300496139706* 1 个月前

$18683857303458* {size} 字节

$21685594109067* 刚才


# Million
$22896492410578* M

$42553566189409* {minutes} 分钟前


# Quadrillion
$49300594926837* Q

$70945526841433* {years} 年前


# Billion
$71072134093858* B

$84076931764831* 1 天前


# Thousand
$84696693690500* K

$86244493049244* {hours} 小时前


# Trillion
$87907122406742* T

$95018143828198* 1 年前

$98363990684104* 1 小时前

$98703677236827* 1 分钟前



=== presenter/board_ui.nim ===

$36331525379247* 保存该电路图



=== presenter/board_ui/bottom_panel.nim ===

$55369640789869* 在电路板上的空白处或元件引脚处按下鼠标拖动，即可绘制导线\n请用导线将与非门和红色的端子连接起来

$79416009887091* 在电路板上任何位置单击，即可将选中的逻辑门放置在电路中

$86840165316981* 右键单击可取消选中当前元件



=== presenter/board_ui/bottom_panel/circular_dependency.nim ===

$13880985462901* 搭建一个电路，让它的输入受自身输出的影响

$16336401898647* 测试 1/2

$22446480186064* 构造一个包含至少 2 个元件的循环依赖结构

$32314337981189* 核对

$73467991035922* 错了！

$89309211963063* 测例 2/2



=== presenter/board_ui/bottom_panel/component_description.nim ===

$10634456248075* 输入 1

$10792411581963* {size} MB

$10967837475411* 输入 1

$12673774208656* 第 1 位

$12729457392140* {size} GB

$12806857886815* 第 0 位

$12955769263032* 输入

$13973719570693* 容量（字节）

$14527438551030* 输入

$14913356525578* 元件开销

$16406822661708* 输入

$17231618567710* 初始数据

$18430168550669* 输出

$23494294864855* 最低 {unit}

$23854618911893* 额外延迟量

$24632471752785* 外部文件

$26116781897961* 元件开销

$27295540163510* 输入 1

$30447216087962* 偏移量

$31208530565026* 输入 0

$32492998000365* 输入 0


# com_static_eval's expression
$32721727081818* 待解算表达式

$34792822299047* 输入 1

$36741466396909* 输入 2

$39848783424235* 输入

$40353371905977* 常量值


# Load a level
$41294322771286* 载入

$45584048068675* 输入 1

$47647445869837* 零值

$48920514303805* 在元件工坊中编辑

$49848147518867* 输入 2

$50011261574308* 输入 1

$50488075986026* 输出

$52764622766005* 输出

$53201813578269* 汇编代码

$55717355371460* 输出

$56555605872372* 输出

$58366024847549* 输入 0

$58805963760936* 正偏移量代表右移，负偏移量代表左移

$59987930153159* 输出

$60193172250813* 若使用新的设定，该元件将占据你真实电脑上 {size} 的内存空间。确定要这样修改吗？

$61114700325299* 输入 0

$64034551286307* 非易失性数据

$64695289448271* 8 位输入中的每一位分别控制数码管一个节段的点亮/熄灭。第八位对应小数点。

$65186041856822* 输出

$65254105186908* 输出

$65365515206856* 注意：尽管键盘元件可以在事件队列中存储多个按键事件，但在每个时钟周期开始（上升沿）时，系统只能读出队列头部的一个按键事件！

$69729205667293* 十六进制编辑器

$70002762618597* 下

$71918065858983* 保存

$75293122338496* 流水线深度（响应周期）

$76078010638637* 导通/断开

$76120552154698* 输入 0

$76125262162505* 输入 1

$77252050278971* 输出

$78475032277779* 输入 0

$80252365204151* 打孔卡片

$81678588906692* 中断消息

$82521178851608* 输入 0

$84542005958715* 标签

$85815999713437* 输入 1

$86658255589213* 可编辑内容

$88655619989708* 输入 0

$88881918807029* 锁定（禁止删除）

$89612128414294* 标签方向

$90286330794518* 输出

$91063734228931* 左

$95419083709418* 使用小端序

$95766090310621* 右

$97169317610794* 上



=== presenter/board_ui/bottom_panel/introduction.nim ===

$24027424800887* 下一关

$70403032472607* 很好！进入下一关吧。

$80966247197959* 点击左侧面板上的“输入”按钮，向电路输入高电平信号 [T]。



=== presenter/board_ui/bottom_panel/nand_gate.nim ===

$32982011047799* 核对

$43078933051174* 点击真值表最后一行的灰色按钮以填写输出值。

$61241226128494* 不对！

$71204033550134* 电路中的与非门有什么效果？



=== presenter/board_ui/bottom_panel/racer_question.nim ===

$95509904060545* 提交



=== presenter/board_ui/bottom_panel/solution_warning.nim ===

$21618236951146* 查看解法

$65770257567603* 若想查看参考解法，请点击下方的按钮。



=== presenter/board_ui/bottom_panel/user_defined_ui.nim ===

$10446152707984* 地址

$20074247151096* 指令

$41540713506719* 指令

$64281970848639* 描述



=== presenter/board_ui/common.nim ===

$10463931654475* 输入 0

$14057674753878* 输入 1

$58374689721038* 字节

$73841752788709* 输入

$74796974148718* 输出



=== presenter/board_ui/component_menu/flat_list.nim ===

$70994998239232* 请点击右侧的与非门，将其选中



=== presenter/board_ui/cycle_info.nim ===

$18403698792036* 关卡类型

$41662660252584* 光标位置

$53456282160464* 沙盒模式

$72245209470436* FPS

$74564675939961* 仿真时钟主频

$99534264629442* 测例



=== presenter/board_ui/file_explorer.nim ===


# Placeholder on the name input field of the file explorer
$18871898542185* 新建文件夹

$56429258960561* 重命名

$69090690657232* 复制


# Load a schematic
$70369485875359* 载入


# Placeholder on the name input field of the file explorer
$84870575118100* 新文件

$91861509153454* 删除



=== presenter/board_ui/function_icons.nim ===

$36396661222670* 右键单击此处以提高模拟时钟主频

$39440928972984* 复位（{key}）

$42454393978813* 点击此按钮，可连续运行所有测例

$53448014080434* 删除（快捷键：右键）

$54853798559740* 快速运行（{key}；右键单击：切换运行速度）

$66405942066048* 上一刻

$68617247634978* 设置位宽 (右键单击：调整位宽值)

$69987793052607* 导线注释（单击线路）

$78287906849040* 导线颜色

$80451578314373* 放大

$80746616574054* 下一周期（{key}；右键单击：跳转到指定时钟帧位）

$84434122873489* 缩小

$85147529532131* 多选（快捷键：SHIFT+左键拖动）



=== presenter/board_ui/io_state_view.nim ===


# MEMORY section title on the left panel
$13690653984793* 输出状态


# MEMORY section title on the left panel
$34156015279634* 存储器状态


# INPUTS section title on the left panel
$64033841051521* 输入状态



=== presenter/board_ui/menu_bar.nim ===

$11731996208080* 元件工坊

$30516879701896* 沙盒模式

$33761197388580* 查看提示

$38557550573896* 关卡说明

$50924073287410* 切换数字格式

$56916384895438* 主菜单

$71951682957395* 浏览关卡

$79554853897000* 切换电路图

$85248932172256* 退出提示模式

$85430022417382* 显示延迟量

$91515053618360* 手册

$98930461722118* 返回



=== presenter/board_ui/menu_bar_campaign.nim ===

$68227209887733* 元件工坊


# Placeholder for the search bar in the level tree
$72813322690589* 搜索关卡



=== presenter/board_ui/popup/address_jumper.nim ===


# OK button on popups
$26766209496460* 确定

$36265530817755* 跳转到指定地址：

$40263691211335* 目标偏移量（16、0xF、……）



=== presenter/board_ui/popup/assembler_watchee_linker.nim ===

$37885763626223* 链接寄存器组

$51331074553774* 要模拟的寄存器总数

$67225915898937* 名称前缀

$67275059688693* 数据位宽

$77103446544344* 例如：reg_

$77741358519166* 寄存器个数



=== presenter/board_ui/popup/cycle_editor.nim ===

$19062117579269* 跳转到时钟周期：



=== presenter/board_ui/popup/cycle_speed_editor.nim ===

$16026817441460* 周期/秒



=== presenter/board_ui/popup/dialogue/info.nim ===

$52150443679969* 继续

$89787506720574* 关闭



=== presenter/board_ui/popup/dialogue/unlock.nim ===

$10090938799865*
[large]手册页面[/large]
条目：[color=#68d277]{page}[/color]

$14047403461014* 总能耗（门数量 x 总耗时）

$16820079067437* 关卡完成

$20801641140962*

[b]关卡树[/b]
[color=#cccccc]点击“[color=#e49f44]继续[/color]”以进入关卡树界面[/color]

$26794262854382* 保留旧电路

$30368115829346* 最慢测例周期数

$32133561664335* 全部保留

$33922330743421*

[b]导线颜色[/b]
[color=#cccccc]用不同的导线颜色来提高电路图的可读性。[/color]

$40510295620397* 覆盖（保留新电路）

$41649402437253*

41649402437253 [b]负数[/b]
[color=#cccccc]在有符号整数模式
和无符号整数模式间切换[/color]

$43462148240207* 每周期指令数

$43591599177045* 单步能耗（门数量 x 延迟量）

$44038153424304* 已有名为“{save}”的存档电路图

$45250062735373* 解锁内容

$51096427131653* 继续

$53037516781370* 存档冲突：

$53389567901907* 已有名为“{comp}”的自定义元件


# This is a level kind, similar to Architecture, Programming & Component levels on the website
$58769207148712* 电路元件关卡

$65428404547905* 关卡小结


# This is a level kind, similar to Architecture, Programming & Component levels on the website
$66101029228279* 编程关卡


# This is a level kind, similar to Architecture, Programming & Component levels on the website
$69219742310717* 计算机架构关卡

$69511102367948* 关卡类型

$72987046679863* 总耗时（延迟量 x 周期数）

$76805548224716* 内存容量过高！系统不会对此解法计分。

$78783902500954*

[b]在线个人资料[/b]
[color=#cccccc]在主菜单中点击“个人资料”即可访问在线个人记录[/color]

$84923734370936* 最慢测例


# This is a level kind, similar to Architecture, Programming & Component levels on the website
$90134890578411* 其它类型关卡

$92313038380926* 关卡

$92673421413755*

[b]导线注释[/b]
[color=#cccccc]为你的导线添加注释文本。[/color]

$94261690850981*

[b]十六进制[/b]
[color=#cccccc]在有符号十进制、无符号十进制和无符号十六进制数值间切换[/color]



=== presenter/board_ui/popup/ide/editor.nim ===


# IDE tab name
$11106925604855* 文件

$11967666262990* 检测到指令集错误！请打开指令集编辑器进行修正。

$13400106910274* 第 {nr} 行：{msg}


# IDE tab name
$88520918982355* 监视的寄存器



=== presenter/board_ui/popup/ide/file_browser.nim ===

$63693638857058* 该文件夹包含 {folders} 个子文件夹。

$66107456188362* 该文件夹包含 {folders} 个子文件夹和 {asm} 个 .asm 汇编文件。

$86093358515620* 该文件夹为空。

$93027749509988* 该文件夹包含 {asm} 个 .asm 汇编文件。



=== presenter/board_ui/popup/ide/tab_list.nim ===

$84832818424728* 文件



=== presenter/board_ui/popup/ide/watcher_list.nim ===

$12944436882589* 添加监视目标



=== presenter/board_ui/popup/instruction_overture.nim ===

$10141348037745* 写入立即数：{nr}

$10366913897135* 点击二进制位以切换数值

$14831276667273* 指令


# The text above the 3 LSBs
$25145891843959* 必定跳转

$26521666422399* 计算

$31185395052385* 输出设备


# The text above the 3 LSBs
$38497477227061* [color=#e49f44]result {condition} 0[/color] 时跳转


# The text above the 3 LSBs
$39935096343723* 必不跳转

$41846451178700* 将 {from} 的值写入 {to} 中。

$43723329256095* REG {nr}

$53665446068319* 未使用

$54909668901048* 立即数


# The text below the byte
$59958585065722* 当 [color=#e49f44]result {condition} 0[/color] 时，将 [color=#DD6576][bold]REG 0[/bold][/color] 的值写入程序计数器

$67413863640193* 任何条件下都不将 [color=#DD6576][bold]REG 0[/bold][/color] 的值写入程序计数器

$81322935207536* 输入设备

$89294533225655* 计算 [color=#DD6576][bold]REG 1[/bold][/color] {operation} [color=#DD6576][bold]REG 2[/bold][/color]

$89662716409733* 无条件地将 [color=#DD6576][bold]REG 0[/bold][/color] 的值写入程序计数器

$92046368194170* 条件

$98983752580592* 复制



=== presenter/board_ui/popup/schematic_browser/file_browser.nim ===

$14436541903929* 下列架构：{list}

$17985924005596* 该文件夹里尚有 {nr} 个电路图。

$38011567415872* 文件夹为空。

$51791491383290* 该元件已被用于

$57790786178566* 下列的自定义元件：{list}

$66392158413243* 确定要删除“{file_name}”吗？

$68586106474430* 提示：计算机架构关卡会读取同一套电路图，该电路删除后会对所有此类关卡造成影响！

$89354977462546* 取消



=== presenter/board_ui/popup/schematic_browser/item_description.nim ===

$15827374884671* 上级文件夹

$19184997172542* 在下列架构中使用：

$23950941073542* 电路名称

$32598300339944* <作为新的电路图副本上传>

$32645745463577* 在下列元件中使用：

$34084132835354* 在元件菜单中显示

$36200352866864* 最近编辑

$38755675398147* 启用线或（WOR）

$54460367152653* 分享

$62604042376934* 导出为 Verilog

$74184088067843* 选择

$84344684205464* 导出路径

$87138477300432* 支持 [image] 和 [link] 之外的 BBCode 格式代码

$87579936985765* 我同意以 [link=`CC0`]CC0[/link] 公共许可协议发布此电路

$95386916091656* 电路描述



=== presenter/board_ui/popup/static_value_editor.nim ===

$54982025748137* 从输入推导位宽

$61685569269160* 自动

$70256730895162* 设定位宽



=== presenter/board_ui/popup/wire_comment_editor.nim ===

$36027984716180* 线路注释



=== presenter/board_ui/racer_question.nim ===

$11176073682097* 二进制下，{number} 如何表示？

$13872783467999* 有符号二进制的 {number} 如何表示?

$19099025738142* 开始

$23959994711260* 准备好了吗？

$37093663674348* 第 {x} 级

$41793938939207* 时间到

$45532697833519* 你达到了第 {level} 级！

$56999237564848* 剩余 {x} 秒

$92057009138253* 十六进制的 {number} 如何表示？



=== presenter/console.nim ===

$63321577947087* 按 Enter 键显示控制台帮助



=== presenter/level_tree_ui.nim ===

$19508086025944* 进阶编程

$26276191141664* 使用方向键平移视图

$35696974632265* 关卡图标颜色

$38100016313511* 进阶处理器架构

$38843517090942* 可运行的计算机

$44937904689376* 编程

$51337598329530* 算术运算

$55841332003989* 降低解法延迟量以通过检测

$65362728703588* 存储器

$75049509201775* 布尔代数

$81337533438394* 已通过

$81707212583931* 已解锁

$87420015169370* 可选元件

$95146987030704* 未解锁

$95559333192525* 处理器架构



=== presenter/main_menu_ui/credits_page.nim ===

$15872341864658*

由衷感谢：

[b]翻译[/b]
{translators}

[b]早期版本测试[/b]
{beta_testers}

[b]字体设计[/b]
{font_work}

[b]Symphony game[/b]
Ettapp

[b]原声带[/b]
{soundtrack}

$21717110565858* 致谢



=== presenter/main_menu_ui/home_page.nim ===

$12639868461113* 退出

$13921098180953* 分享中心

$15234594767991* 致谢

$16857608955464* 沙盒模式

$32835651830157* 个人资料

$49251062339706* 选项

$66967233942803* 开始游戏



=== presenter/main_menu_ui/hub/description.nim ===


# The hub schematic size
$15762392983604* 大小：

$22639280459994* 加载中…

$44524092309946* 加载中…


# To download hub schematics
$55983490912314* 载入

$61693098943939* 继续


# To delete hub schematics
$62589392744014* 删除


# To confirm deleting hub schematics
$66333328482057* 确定从分享中心删除该电路吗？


# The hub author
$71812400203030* 作者：

$76747661573536* 确定

$76770986264566* 搜索

$84668607423763* 下载电路前，你需要先禁用 Windows 的默认路径长度限制。单击“继续”按钮后，游戏将会弹窗提示你修改注册表，请点击确认以完成禁用操作。路径长度限制是一项历史遗留设置，在现代 Windows 中已经没有继续启用的必要。

$90731554079332* 暂无此类电路图



=== presenter/main_menu_ui/hub/filter.nim ===

$23829497228009* 类型

$25536941657464* 电路元件

$43488408276984* 最受欢迎

$56045953383535* 计算机架构

$70134513915163* 最新上传

$77788981567936* 关卡

$83319579232915* 排列顺序

$87115430626073* 我的电路



=== presenter/main_menu_ui/options/control_tab.nim ===

$13231048881956* 时钟复位

$15032124477918* 选取线路颜色 4

$20313704155593* 选取线路颜色 6

$21380256293472* 全选

$33884219481037* 视图右移

$36372993787575* 选取线路颜色 1

$50610605761210* 恢复

$52159578521318* 粘贴

$53266310714298* 控制

$55156524671891* 选取线路颜色 5

$58334563411624* 撤销

$58442122157391* 导线上色

$60118970740682* 快速运行

$64529333110609* 选取线路颜色 7

$66251711975517* 选取线路颜色 9

$67362258372706* 导线簇上色

$74309706297402* 复制

$76995246992803* 选取线路颜色 10

$77819900580235* 选取线路颜色 2

$78515694621006* 视图左移

$78673220868687* 选取线路颜色 8

$78777350869870* 请按下要设定的新键位

$80031998727851* 视图上移

$83373647697807* 选取线路颜色 3

$86574817679356* 下一周期（时钟步进）

$87273391208106* 选取线路颜色 0

$88236351843942* 旋转

$88238310953306* 剪切

$93140495547084* 视图下移

$96339976117958* 拾取线路颜色

$96449970906640* 添加线路注释

$96601731563408* 打开控制台



=== presenter/main_menu_ui/options/general_tab.nim ===

$12034378482152* 确定重置游戏吗？

$13442839894535* 导线动画速度

$15557473522933* 重置

$21908594290225* 通用选项

$23270083417453* 取消

$24145565754506* 音效音量

$29594613477534* 界面语言将在重启游戏后变更。

$30910326565868* 语言

$49806848871093* 色盲辅助模式

$54328660964287* 窗口模式

$55047615798435* 为交互式小游戏关闭竞速计时

$61172959716558* 存档路径

$67420270098223* 重置为出厂状态

$70994568832660* 确定清除

$71208664264770*

该操作会清除已有的游戏进度、全部关卡解法、自定义元件和架构电路图。
此操作无法撤销！
你确定要这么做吗？
点击“确定清除”按钮后，游戏将会退出。下次重启时，游戏会完全重置。

$93981778736076* 音乐音量

$95307230990123* Verilog 模式



=== presenter/main_menu_ui/options/page.nim ===

$36195388998735* 通用



=== presenter/markup/markup.nim ===

$66207112287034* 提示



=== presenter/update_state_common.nim ===

$13327741293223* 输入 {nr}

$29169064199243* 输出 {nr}

$39906291838542* 时钟周期

$43118901497406* 总延迟

$70170261551278* 总能耗

$95192766583497* 门数量



=== presenter/update_state_stream.nim ===

$12823129240050* 单击左上角的链接按钮以将屏幕和选定的存储器关联起来。


# Text on keyboard component
$41639816417947* “快速运行”时监听键盘


# Text on keyboard component
$61909856780806* 正在监听键盘


# Text on keyboard component
$73297471730751* 未监听



=== presenter/user_input/board_io/action/none.nim ===

$10186190492148* ALT+鼠标左键单击：移动导通孔

$22780831606716* 载入文件

$26085882338208* 编辑打孔卡片

$38481453712356* 编辑程序

$64854367750357* 打开十六进制编辑器

$80005228759908* 在此输入值：

$98772447663910* 编辑监视态



=== presenter/utilities.nim ===


# Switched Output is the name under 19513138880387
$12249248261034* 要通过本关，你必须使用“三态输出”元件

$12256736989028* 同一方格内存在多于一个探针。由于探针重叠，当前元件将无法使用。

$14665712485657* 该元件面积为零，无法放置。

$15549447390000* 同一个方格内有两个输入/输出端子。由于引脚重叠，当前元件将无法使用。

$18997072674417* 你用到的<元件>本关里尚未解锁。

$25337574230078* 同一个方格内有两个输入/输出端子。由于引脚重叠，当前元件将无法使用。

$27322222841583* 元件“<>”和“<>”发生短路

$29718660090112* 答案错误

$32087108522443* 静态位宽指示引脚（蓝色）只能与其它蓝色引脚相连。

$42649958199625* 当前游戏进度受到了关卡图更新的影响。请完成<对应关卡>以修复问题。

$44947135063289* 检测到循环依赖 - 元件的输出接入到了自身的输入端。

$45545544521085* <元件>的位置无效。

$45678915971282* <自定义元件>内部发生短路。

$47880883686501* 检测到循环依赖 - 元件的输出接入到了自身的输入端。请参阅手册中的“循环依赖”页面以了解相关内容。

$48909199348313* 输出正确，但电路延迟量超过 {max_delay}

$51332486391182* 瓶颈路径位于该<自定义元件>中。

$51730362111148* <自定义元件>中的 {name} 本关里尚未解锁。

$56798729463813* 关卡源代码损坏。

$73948669941805* 输出正确，但电路基础逻辑门总数超过 {max_gates}


# Switched Input is the name under 11278573510238
$95056157627313* 要通过本关，你必须使用“三态输入”元件



=== presenter/utilities/helper_functions.nim ===


# Fallback for component name on the left panel
$11467644007149* {nr} 号计数器


# Fallback for component name on the left panel
$11980538317261* 内存


# Fallback for component name on the left panel
$19471584538385* 输入

$25272818268849*

[b]本关总结[/b]

通过这一关的练习，希望你已经了解了二进制表示法的特点：
1. 每个整数在二进制下的表示方式是唯一的。
2. 每个数位对应的数值都是下一个数位的 2 倍。

$37319690622142* 干得漂亮，你的成绩达到第 {current_level} 级了。


# Fallback for component name on the left panel
$41936481068702* 计数器


# Fallback for component name on the left panel
$42012207828907* 寄存器


# Fallback for component name on the left panel
$44820775847452* 输出

$87016829502381* 干得漂亮，你的成绩达到第 {current_level} 级了。


# Fallback for component name on the left panel
$87591753278764* {nr} 号寄存器

$97450409600317*

[b]本关要点[/b]

1. 要在正负数之间相互转换，你需要先将所有二进制位反转，然后再将结果加 1。
2. 如果最高位是 [T]，那么这个数一定是负数。
3. 你先前搭建的加法器可以直接用在补码表示的负数上。
4. 每个整数的表示方式仍然是唯一的。


# Fallback for component name on the left panel
$97889215332379* {nr} 号内存

